diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 5eb37b0a0..000000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,79 +0,0 @@ -version: 2.1 - -orbs: - ship: auth0/ship@0.6.1 - codecov: codecov/codecov@3 - -commands: - checkout-and-build: - steps: - - checkout - - run: chmod +x gradlew - # Download and cache dependencies - - restore_cache: - keys: - - v1-dependencies-{{ checksum "build.gradle" }} - # fallback to using the latest cache if no exact match is found - - v1-dependencies- - - run: ./gradlew clean build - - save_cache: - paths: - - ~/.m2 - key: v1-dependencies-{{ checksum "build.gradle" }} - - run-tests: - steps: - - run: ./gradlew check jacocoTestReport --continue --console=plain - - codecov/upload - - run-api-diff: - steps: - # run apiDiff task - - run: ./gradlew apiDiff - - store_artifacts: - path: build/reports/apiDiff/apiDiff.txt - - store_artifacts: - path: build/reports/apiDiff/apiDiff.html - -jobs: - build: - docker: - - image: openjdk:8-jdk - steps: - - checkout-and-build - - run-tests - environment: - GRADLE_OPTS: '-Dorg.gradle.jvmargs="-Xmx2048m -XX:+HeapDumpOnOutOfMemoryError"' - _JAVA_OPTIONS: "-Xms512m -Xmx1024m" - TERM: dumb - - api-diff: - docker: - - image: openjdk:8-jdk - steps: - - checkout-and-build - - run-api-diff - environment: - GRADLE_OPTS: '-Dorg.gradle.jvmargs="-Xmx2048m -XX:+HeapDumpOnOutOfMemoryError"' - _JAVA_OPTIONS: "-Xms512m -Xmx1024m" - TERM: dumb - -workflows: - build-and-test: - jobs: - - build - - ship/java-publish: - prefix-tag: false - context: - - publish-gh - - publish-sonatype - filters: - branches: - only: - - master - requires: - - build - - api-diff: - jobs: - - api-diff diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 60f116c05..7958e8bdd 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1 @@ -* @auth0/dx-sdks-engineer +* @auth0/project-dx-sdks-engineer-codeowner diff --git a/.github/ISSUE_TEMPLATE/Bug Report.yml b/.github/ISSUE_TEMPLATE/Bug Report.yml new file mode 100644 index 000000000..18383e60e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Bug Report.yml @@ -0,0 +1,67 @@ +name: 🐞 Report a bug +description: Have you found a bug or issue? Create a bug report for this library +labels: ["bug"] + +body: + - type: markdown + attributes: + value: | + **Please do not report security vulnerabilities here**. The [Responsible Disclosure Program](https://auth0.com/responsible-disclosure-policy) details the procedure for disclosing security issues. + + - type: checkboxes + id: checklist + attributes: + label: Checklist + options: + - label: I have looked into the [Readme](https://github.com/auth0/auth0-java#readme) and [Examples](https://github.com/auth0/auth0-java/blob/master/EXAMPLES.md), and have not found a suitable solution or answer. + required: true + - label: I have looked into the [API documentation](https://javadoc.io/doc/com.auth0/auth0/latest/index.html) and have not found a suitable solution or answer. + required: true + - label: I have searched the [issues](https://github.com/auth0/auth0-java/issues) and have not found a suitable solution or answer. + required: true + - label: I have searched the [Auth0 Community](https://community.auth0.com) forums and have not found a suitable solution or answer. + required: true + - label: I agree to the terms within the [Auth0 Code of Conduct](https://github.com/auth0/open-source-template/blob/master/CODE-OF-CONDUCT.md). + required: true + + - type: textarea + id: description + attributes: + label: Description + description: Provide a clear and concise description of the issue, including what you expected to happen. + validations: + required: true + + - type: textarea + id: reproduction + attributes: + label: Reproduction + description: Detail the steps taken to reproduce this error, and whether this issue can be reproduced consistently or if it is intermittent. + placeholder: | + 1. Step 1... + 2. Step 2... + 3. ... + validations: + required: true + + - type: textarea + id: additional-context + attributes: + label: Additional context + description: Other libraries that might be involved, or any other relevant information you think would be useful. + validations: + required: false + + - type: input + id: environment-version + attributes: + label: auth0-java version + validations: + required: true + + - type: input + id: environment-java-version + attributes: + label: Java version + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/Feature Request.yml b/.github/ISSUE_TEMPLATE/Feature Request.yml new file mode 100644 index 000000000..d8679879c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Feature Request.yml @@ -0,0 +1,53 @@ +name: 🧩 Feature request +description: Suggest an idea or a feature for this library +labels: ["feature request"] + +body: + - type: checkboxes + id: checklist + attributes: + label: Checklist + options: + - label: I have looked into the [Readme](https://github.com/auth0/auth0-java#readme) and [Examples](https://github.com/auth0/auth0-java/blob/master/EXAMPLES.md), and have not found a suitable solution or answer. + required: true + - label: I have looked into the [API documentation](https://javadoc.io/doc/com.auth0/auth0/latest/index.html) and have not found a suitable solution or answer. + required: true + - label: I have searched the [issues](https://github.com/auth0/auth0-java/issues) and have not found a suitable solution or answer. + required: true + - label: I have searched the [Auth0 Community](https://community.auth0.com) forums and have not found a suitable solution or answer. + required: true + - label: I agree to the terms within the [Auth0 Code of Conduct](https://github.com/auth0/open-source-template/blob/master/CODE-OF-CONDUCT.md). + required: true + + - type: textarea + id: description + attributes: + label: Describe the problem you'd like to have solved + description: A clear and concise description of what the problem is. + placeholder: I'm always frustrated when... + validations: + required: true + + - type: textarea + id: ideal-solution + attributes: + label: Describe the ideal solution + description: A clear and concise description of what you want to happen. + validations: + required: true + + - type: textarea + id: alternatives-and-workarounds + attributes: + label: Alternatives and current workarounds + description: A clear and concise description of any alternatives you've considered or any workarounds that are currently in place. + validations: + required: false + + - type: textarea + id: additional-context + attributes: + label: Additional context + description: Add any other context or screenshots about the feature request here. + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index e2b020fc8..65c99a9ce 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,8 +1,5 @@ blank_issues_enabled: false contact_links: - name: Auth0 Community - url: https://community.auth0.com/c/sdks/5 + url: https://community.auth0.com about: Discuss this SDK in the Auth0 Community forums - - name: Library Documentation - url: https://github.com/auth0/auth0-java/blob/master/README.md - about: Read the library documentation diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index 68352ba23..000000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -name: Feature request -about: Suggest an idea or a feature for this project -title: '' -labels: feature request -assignees: '' ---- - - - -### Describe the problem you'd like to have solved - - - -### Describe the ideal solution - - - -## Alternatives and current work-arounds - - - -### Additional information, if any - - \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/report-a-bug.md b/.github/ISSUE_TEMPLATE/report-a-bug.md deleted file mode 100644 index 0ecb939d7..000000000 --- a/.github/ISSUE_TEMPLATE/report-a-bug.md +++ /dev/null @@ -1,55 +0,0 @@ ---- -name: Report a bug -about: Have you found a bug or issue? Create a bug report for this SDK -title: '' -labels: bug report -assignees: '' ---- - - - -### Describe the problem - - - -### What was the expected behavior? - - - -### Reproduction - - -- Step 1.. -- Step 2.. -- ... - -### Environment - - - -- **Version of this library used:** -- **Version of Java used:** -- **Other modules/plugins/libraries that might be involved:** -- **Any other relevant information you think would be useful:** \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/report_a_bug.md b/.github/ISSUE_TEMPLATE/report_a_bug.md deleted file mode 100644 index 50b9fa7eb..000000000 --- a/.github/ISSUE_TEMPLATE/report_a_bug.md +++ /dev/null @@ -1,55 +0,0 @@ ---- -name: Report a bug -about: Have you found a bug or issue? Create a bug report for this SDK -title: '' -labels: bug report -assignees: '' ---- - - - -### Describe the problem - - - -### What was the expected behavior? - - - -### Reproduction - - -- Step 1.. -- Step 2.. -- ... - -### Environment - - - -- **Version of this library used:** -- **Which framework are you using, if applicable:** -- **Other modules/plugins/libraries that might be involved:** -- **Any other relevant information you think would be useful:** \ No newline at end of file diff --git a/.github/actions/get-prerelease/action.yml b/.github/actions/get-prerelease/action.yml new file mode 100644 index 000000000..ce7acdc3b --- /dev/null +++ b/.github/actions/get-prerelease/action.yml @@ -0,0 +1,30 @@ +name: Return a boolean indicating if the version contains prerelease identifiers + +# +# Returns a simple true/false boolean indicating whether the version indicates it's a prerelease or not. +# +# TODO: Remove once the common repo is public. +# + +inputs: + version: + required: true + +outputs: + prerelease: + value: ${{ steps.get_prerelease.outputs.PRERELEASE }} + +runs: + using: composite + + steps: + - id: get_prerelease + shell: bash + run: | + if [[ "${VERSION}" == *"beta"* || "${VERSION}" == *"alpha"* ]]; then + echo "PRERELEASE=true" >> $GITHUB_OUTPUT + else + echo "PRERELEASE=false" >> $GITHUB_OUTPUT + fi + env: + VERSION: ${{ inputs.version }} diff --git a/.github/actions/get-release-notes/action.yml b/.github/actions/get-release-notes/action.yml new file mode 100644 index 000000000..287d2066c --- /dev/null +++ b/.github/actions/get-release-notes/action.yml @@ -0,0 +1,42 @@ +name: Return the release notes extracted from the body of the PR associated with the release. + +# +# Returns the release notes from the content of a pull request linked to a release branch. It expects the branch name to be in the format release/vX.Y.Z, release/X.Y.Z, release/vX.Y.Z-beta.N. etc. +# +# TODO: Remove once the common repo is public. +# +inputs: + version: + required: true + repo_name: + required: false + repo_owner: + required: true + token: + required: true + +outputs: + release-notes: + value: ${{ steps.get_release_notes.outputs.RELEASE_NOTES }} + +runs: + using: composite + + steps: + - uses: actions/github-script@v7 + id: get_release_notes + with: + result-encoding: string + script: | + const { data: pulls } = await github.rest.pulls.list({ + owner: process.env.REPO_OWNER, + repo: process.env.REPO_NAME, + state: 'all', + head: `${process.env.REPO_OWNER}:release/${process.env.VERSION}`, + }); + core.setOutput('RELEASE_NOTES', pulls[0].body); + env: + GITHUB_TOKEN: ${{ inputs.token }} + REPO_OWNER: ${{ inputs.repo_owner }} + REPO_NAME: ${{ inputs.repo_name }} + VERSION: ${{ inputs.version }} diff --git a/.github/actions/get-version/action.yml b/.github/actions/get-version/action.yml new file mode 100644 index 000000000..9440ec920 --- /dev/null +++ b/.github/actions/get-version/action.yml @@ -0,0 +1,21 @@ +name: Return the version extracted from the branch name + +# +# Returns the version from the .version file. +# +# TODO: Remove once the common repo is public. +# + +outputs: + version: + value: ${{ steps.get_version.outputs.VERSION }} + +runs: + using: composite + + steps: + - id: get_version + shell: bash + run: | + VERSION=$(head -1 .version) + echo "VERSION=${VERSION}" >> $GITHUB_OUTPUT diff --git a/.github/actions/maven-publish/action.yml b/.github/actions/maven-publish/action.yml new file mode 100644 index 000000000..b99ed108a --- /dev/null +++ b/.github/actions/maven-publish/action.yml @@ -0,0 +1,45 @@ +name: Publish release to Java + +inputs: + java-version: + required: true + ossr-username: + required: true + ossr-token: + required: true + signing-key: + required: true + signing-password: + required: true + + +runs: + using: composite + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Java + shell: bash + run: | + curl -s "https://get.sdkman.io" | bash + source "/home/runner/.sdkman/bin/sdkman-init.sh" + sdk list java + sdk install java ${{ inputs.java-version }} && sdk default java ${{ inputs.java-version }} + export JAVA_HOME=${SDKMAN_DIR}/candidates/java/current + echo "JAVA_HOME is set to $JAVA_HOME" + + - uses: gradle/wrapper-validation-action@56b90f209b02bf6d1deae490e9ef18b21a389cd4 # pin@1.1.0 + env: + JAVA_HOME: ${{ env.JAVA_HOME }} + + - name: Publish Android/Java Packages to Maven + shell: bash + run: ./gradlew publishToSonatype closeSonatypeStagingRepository -PisSnapshot=false --stacktrace + env: + JAVA_HOME: ${{ env.JAVA_HOME }} + MAVEN_USERNAME: ${{ inputs.ossr-username }} + MAVEN_PASSWORD: ${{ inputs.ossr-token }} + SIGNING_KEY: ${{ inputs.signing-key}} + SIGNING_PASSWORD: ${{ inputs.signing-password}} diff --git a/.github/actions/release-create/action.yml b/.github/actions/release-create/action.yml new file mode 100644 index 000000000..6a2bf804c --- /dev/null +++ b/.github/actions/release-create/action.yml @@ -0,0 +1,47 @@ +name: Create a GitHub release + +# +# Creates a GitHub release with the given version. +# +# TODO: Remove once the common repo is public. +# + +inputs: + token: + required: true + files: + required: false + name: + required: true + body: + required: true + tag: + required: true + commit: + required: true + draft: + default: false + required: false + prerelease: + default: false + required: false + fail_on_unmatched_files: + default: true + required: false + +runs: + using: composite + + steps: + - uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 + with: + body: ${{ inputs.body }} + name: ${{ inputs.name }} + tag_name: ${{ inputs.tag }} + target_commitish: ${{ inputs.commit }} + draft: ${{ inputs.draft }} + prerelease: ${{ inputs.prerelease }} + fail_on_unmatched_files: ${{ inputs.fail_on_unmatched_files }} + files: ${{ inputs.files }} + env: + GITHUB_TOKEN: ${{ inputs.token }} diff --git a/.github/actions/rl-scanner/action.yml b/.github/actions/rl-scanner/action.yml new file mode 100644 index 000000000..03c378a0c --- /dev/null +++ b/.github/actions/rl-scanner/action.yml @@ -0,0 +1,71 @@ +name: "Reversing Labs Scanner" +description: "Runs the Reversing Labs scanner on a specified artifact." +inputs: + artifact-path: + description: "Path to the artifact to be scanned." + required: true + version: + description: "Version of the artifact." + required: true + +runs: + using: "composite" + steps: + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.10" + + - name: Install Python dependencies + shell: bash + run: | + pip install boto3 requests + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v1 + with: + role-to-assume: ${{ env.PRODSEC_TOOLS_ARN }} + aws-region: us-east-1 + mask-aws-account-id: true + + - name: Install RL Wrapper + shell: bash + run: | + pip install rl-wrapper>=1.0.0 --index-url "https://${{ env.PRODSEC_TOOLS_USER }}:${{ env.PRODSEC_TOOLS_TOKEN }}@a0us.jfrog.io/artifactory/api/pypi/python-local/simple" + + - name: Run RL Scanner + shell: bash + env: + RLSECURE_LICENSE: ${{ env.RLSECURE_LICENSE }} + RLSECURE_SITE_KEY: ${{ env.RLSECURE_SITE_KEY }} + SIGNAL_HANDLER_TOKEN: ${{ env.SIGNAL_HANDLER_TOKEN }} + PYTHONUNBUFFERED: 1 + run: | + if [ ! -f "${{ inputs.artifact-path }}" ]; then + echo "Artifact not found: ${{ inputs.artifact-path }}" + exit 1 + fi + + rl-wrapper \ + --artifact "${{ inputs.artifact-path }}" \ + --name "${{ github.event.repository.name }}" \ + --version "${{ inputs.version }}" \ + --repository "${{ github.repository }}" \ + --commit "${{ github.sha }}" \ + --build-env "github_actions" \ + --suppress_output + + # Check the outcome of the scanner + if [ $? -ne 0 ]; then + echo "RL Scanner failed." + echo "scan-status=failed" >> $GITHUB_ENV + exit 1 + else + echo "RL Scanner passed." + echo "scan-status=success" >> $GITHUB_ENV + fi + +outputs: + scan-status: + description: "The outcome of the scan process." + value: ${{ env.scan-status }} diff --git a/.github/actions/tag-exists/action.yml b/.github/actions/tag-exists/action.yml new file mode 100644 index 000000000..b5fbdb730 --- /dev/null +++ b/.github/actions/tag-exists/action.yml @@ -0,0 +1,36 @@ +name: Return a boolean indicating if a tag already exists for the repository + +# +# Returns a simple true/false boolean indicating whether the tag exists or not. +# +# TODO: Remove once the common repo is public. +# + +inputs: + token: + required: true + tag: + required: true + +outputs: + exists: + description: 'Whether the tag exists or not' + value: ${{ steps.tag-exists.outputs.EXISTS }} + +runs: + using: composite + + steps: + - id: tag-exists + shell: bash + run: | + GET_API_URL="https://api.github.com/repos/${GITHUB_REPOSITORY}/git/ref/tags/${TAG_NAME}" + http_status_code=$(curl -LI $GET_API_URL -o /dev/null -w '%{http_code}\n' -s -H "Authorization: token ${GITHUB_TOKEN}") + if [ "$http_status_code" -ne "404" ] ; then + echo "EXISTS=true" >> $GITHUB_OUTPUT + else + echo "EXISTS=false" >> $GITHUB_OUTPUT + fi + env: + TAG_NAME: ${{ inputs.tag }} + GITHUB_TOKEN: ${{ inputs.token }} diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..8cc9d6684 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,14 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" + + - package-ecosystem: "gradle" + directory: "lib" + schedule: + interval: "daily" + ignore: + - dependency-name: "*" + update-types: ["version-update:semver-major"] diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml new file mode 100644 index 000000000..fece2c04f --- /dev/null +++ b/.github/workflows/build-and-test.yml @@ -0,0 +1,31 @@ +name: auth0/auth0-java/build-and-test + +on: + pull_request: + merge_group: + push: + branches: ["master", "main", "v1"] + +jobs: + gradle: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - uses: actions/setup-java@v5 + with: + distribution: temurin + java-version: 8 + + - name: Set up Gradle + uses: gradle/actions/setup-gradle@4d9f0ba0025fe599b4ebab900eb7f3a1d93ef4c2 # v5.0.0 + + - name: Test and Assemble and ApiDiff with Gradle + run: ./gradlew assemble apiDiff check jacocoTestReport --continue --console=plain + + - uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # v5.5.1 + with: + flags: unittests + - uses: actions/upload-artifact@v5 + with: + name: Reports + path: build/reports diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml new file mode 100644 index 000000000..95ca681e3 --- /dev/null +++ b/.github/workflows/claude-code-review.yml @@ -0,0 +1,11 @@ +name: Claude Code PR Review + +on: + issue_comment: + types: [ created ] + pull_request_review_comment: + types: [ created ] + +jobs: + claude-review: + uses: auth0/auth0-ai-pr-analyzer-gh-action/.github/workflows/claude-code-review.yml@main diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml index a015578a8..096fd3dfc 100644 --- a/.github/workflows/gradle-wrapper-validation.yml +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -6,5 +6,5 @@ jobs: name: "validation/gradlew" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: gradle/wrapper-validation-action@v1 + - uses: actions/checkout@v6 + - uses: gradle/actions/wrapper-validation@v5 diff --git a/.github/workflows/java-release.yml b/.github/workflows/java-release.yml new file mode 100644 index 000000000..89e7b9c09 --- /dev/null +++ b/.github/workflows/java-release.yml @@ -0,0 +1,92 @@ +name: Create Java and GitHub Release + +on: + workflow_call: + inputs: + java-version: + required: true + type: string + + secrets: + ossr-username: + required: true + ossr-token: + required: true + signing-key: + required: true + signing-password: + required: true + github-token: + required: true + +### TODO: Replace instances of './.github/actions/' w/ `auth0/dx-sdk-actions/` and append `@latest` after the common `dx-sdk-actions` repo is made public. +### TODO: Also remove `get-prerelease`, `get-version`, `release-create`, `tag-create` and `tag-exists` actions from this repo's .github/actions folder once the repo is public. + +jobs: + release: + if: github.event_name == 'workflow_dispatch' || (github.event_name == 'pull_request' && github.event.pull_request.merged && startsWith(github.event.pull_request.head.ref, 'release/')) + runs-on: ubuntu-latest + environment: release + + steps: + # Checkout the code + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + + # Get the version from the branch name + - id: get_version + uses: ./.github/actions/get-version + + # Get the prerelease flag from the branch name + - id: get_prerelease + uses: ./.github/actions/get-prerelease + with: + version: ${{ steps.get_version.outputs.version }} + + # Get the release notes + - id: get_release_notes + uses: ./.github/actions/get-release-notes + with: + token: ${{ secrets.github-token }} + version: ${{ steps.get_version.outputs.version }} + repo_owner: ${{ github.repository_owner }} + repo_name: ${{ github.event.repository.name }} + + # Check if the tag already exists + - id: tag_exists + uses: ./.github/actions/tag-exists + with: + tag: ${{ steps.get_version.outputs.version }} + token: ${{ secrets.github-token }} + + # If the tag already exists, exit with an error + - if: steps.tag_exists.outputs.exists == 'true' + run: exit 1 + + # Set JAVA_HOME here and pass it to subsequent steps + - name: Set JAVA_HOME for Gradle + run: echo "JAVA_HOME=/home/runner/.sdkman/candidates/java/current" >> $GITHUB_ENV # This ensures JAVA_HOME is set globally + env: + SDKMAN_DIR: /home/runner/.sdkman + + # Publish the release to Maven + - uses: ./.github/actions/maven-publish + with: + java-version: ${{ inputs.java-version }} + ossr-username: ${{ secrets.ossr-username }} + ossr-token: ${{ secrets.ossr-token }} + signing-key: ${{ secrets.signing-key }} + signing-password: ${{ secrets.signing-password }} + env: + JAVA_HOME: ${{ env.JAVA_HOME }} + + # Create a release for the tag + - uses: ./.github/actions/release-create + with: + token: ${{ secrets.github-token }} + name: ${{ steps.get_version.outputs.version }} + body: ${{ steps.get_release_notes.outputs.release-notes }} + tag: ${{ steps.get_version.outputs.version }} + commit: ${{ github.sha }} + prerelease: ${{ steps.get_prerelease.outputs.prerelease }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..5bab2bc72 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,40 @@ +name: Create GitHub Release + +on: + pull_request: + types: + - closed + workflow_dispatch: + +permissions: + contents: write + id-token: write # This is required for requesting the JWT + +### TODO: Replace instances of './.github/workflows/' w/ `auth0/dx-sdk-actions/workflows/` and append `@latest` after the common `dx-sdk-actions` repo is made public. +### TODO: Also remove `get-prerelease`, `get-release-notes`, `get-version`, `maven-publish`, `release-create`, and `tag-exists` actions from this repo's .github/actions folder once the repo is public. +### TODO: Also remove `java-release` workflow from this repo's .github/workflows folder once the repo is public. + +jobs: + rl-scanner: + uses: ./.github/workflows/rl-scanner.yml + with: + java-version: 8 + artifact-name: "auth0-java.tgz" + secrets: + RLSECURE_LICENSE: ${{ secrets.RLSECURE_LICENSE }} + RLSECURE_SITE_KEY: ${{ secrets.RLSECURE_SITE_KEY }} + SIGNAL_HANDLER_TOKEN: ${{ secrets.SIGNAL_HANDLER_TOKEN }} + PRODSEC_TOOLS_USER: ${{ secrets.PRODSEC_TOOLS_USER }} + PRODSEC_TOOLS_TOKEN: ${{ secrets.PRODSEC_TOOLS_TOKEN }} + PRODSEC_TOOLS_ARN: ${{ secrets.PRODSEC_TOOLS_ARN }} + release: + uses: ./.github/workflows/java-release.yml + needs: rl-scanner + with: + java-version: 8.0.382-tem + secrets: + ossr-username: ${{ secrets.OSSR_USERNAME }} + ossr-token: ${{ secrets.OSSR_TOKEN }} + signing-key: ${{ secrets.SIGNING_KEY }} + signing-password: ${{ secrets.SIGNING_PASSWORD }} + github-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/rl-scanner.yml b/.github/workflows/rl-scanner.yml new file mode 100644 index 000000000..1455774ea --- /dev/null +++ b/.github/workflows/rl-scanner.yml @@ -0,0 +1,70 @@ +name: RL-Secure Workflow + +on: + workflow_call: + inputs: + java-version: + required: true + type: string + artifact-name: + required: true + type: string + secrets: + RLSECURE_LICENSE: + required: true + RLSECURE_SITE_KEY: + required: true + SIGNAL_HANDLER_TOKEN: + required: true + PRODSEC_TOOLS_USER: + required: true + PRODSEC_TOOLS_TOKEN: + required: true + PRODSEC_TOOLS_ARN: + required: true +jobs: + checkout-build-scan-only: + if: github.event_name == 'workflow_dispatch' || (github.event_name == 'pull_request' && github.event.pull_request.merged && startsWith(github.event.pull_request.head.ref, 'release/')) + runs-on: ubuntu-latest + outputs: + scan-status: ${{ steps.rl-scan-conclusion.outcome }} + + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Set up Java + uses: actions/setup-java@v5 + with: + distribution: temurin + java-version: ${{ inputs.java-version }} + + - name: Set up Gradle + uses: gradle/actions/setup-gradle@4d9f0ba0025fe599b4ebab900eb7f3a1d93ef4c2 # v5.0.0 + + - name: Test and Assemble and ApiDiff with Gradle + run: ./gradlew assemble apiDiff check jacocoTestReport --continue --console=plain + + - id: get_version + uses: ./.github/actions/get-version + + - name: Create tgz build artifact + run: | + tar -czvf ${{ inputs.artifact-name }} * + + - name: Run RL Scanner + id: rl-scan-conclusion + uses: ./.github/actions/rl-scanner + with: + artifact-path: "$(pwd)/${{ inputs.artifact-name }}" + version: "${{ steps.get_version.outputs.version }}" + env: + RLSECURE_LICENSE: ${{ secrets.RLSECURE_LICENSE }} + RLSECURE_SITE_KEY: ${{ secrets.RLSECURE_SITE_KEY }} + SIGNAL_HANDLER_TOKEN: ${{ secrets.SIGNAL_HANDLER_TOKEN }} + PRODSEC_TOOLS_USER: ${{ secrets.PRODSEC_TOOLS_USER }} + PRODSEC_TOOLS_TOKEN: ${{ secrets.PRODSEC_TOOLS_TOKEN }} + PRODSEC_TOOLS_ARN: ${{ secrets.PRODSEC_TOOLS_ARN }} + + - name: Output scan result + run: echo "scan-status=${{ steps.rl-scan-conclusion.outcome }}" >> $GITHUB_ENV diff --git a/.github/workflows/semgrep.yml b/.github/workflows/semgrep.yml deleted file mode 100644 index e0227e37c..000000000 --- a/.github/workflows/semgrep.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: Semgrep - -on: - pull_request: {} - - push: - branches: ["master", "main"] - - schedule: - - cron: '30 0 1,15 * *' - -jobs: - semgrep: - name: Scan - runs-on: ubuntu-latest - container: - image: returntocorp/semgrep - if: (github.actor != 'dependabot[bot]') - steps: - - uses: actions/checkout@v3 - - - run: semgrep ci - env: - SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }} diff --git a/.github/workflows/snyk.yml b/.github/workflows/snyk.yml new file mode 100644 index 000000000..90a7c5213 --- /dev/null +++ b/.github/workflows/snyk.yml @@ -0,0 +1,39 @@ +name: Snyk + +on: + merge_group: + workflow_dispatch: + pull_request: + types: + - opened + - synchronize + push: + branches: + - master + schedule: + - cron: '30 0 1,15 * *' + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} + +jobs: + + check: + name: Check for Vulnerabilities + runs-on: ubuntu-latest + + steps: + - if: github.actor == 'dependabot[bot]' || github.event_name == 'merge_group' + run: exit 0 # Skip unnecessary test runs for dependabot and merge queues. Artifically flag as successful, as this is a required check for branch protection. + + - uses: actions/checkout@v6 + with: + ref: ${{ github.event.pull_request.head.sha || github.ref }} + + - uses: snyk/actions/gradle-jdk11@9adf32b1121593767fc3c057af55b55db032dc04 # pin@1.0.0 + env: + SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} diff --git a/.semgrepignore b/.semgrepignore new file mode 100644 index 000000000..2ebacf0c1 --- /dev/null +++ b/.semgrepignore @@ -0,0 +1 @@ +src/test/ diff --git a/.shiprc b/.shiprc index aee9facba..f81a9f797 100644 --- a/.shiprc +++ b/.shiprc @@ -1,7 +1,8 @@ { "files": { - "build.gradle": [], - "README.md": [] + "README.md": [], + ".version": [], + "build.gradle": ["version = \"{MAJOR}.{MINOR}.{PATCH}\""] }, "prefixVersion": false } diff --git a/.snyk b/.snyk new file mode 100644 index 000000000..cf6ee0132 --- /dev/null +++ b/.snyk @@ -0,0 +1,25 @@ +# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities. +version: v1.25.0 +# ignores vulnerabilities until expiry date; change duration by modifying expiry date +ignore: + SNYK-JAVA-ORGJETBRAINSKOTLIN-2393744: + - '*': + reason: 'unaffected, only affects createTempFile and createTempDir kotlin function, which are not used' + expires: 2024-12-31T00:00:00.000Z + SNYK-JAVA-ORGBOUNCYCASTLE-5771339: + - '*': + reason: 'test-only dependency, no update available' + expires: 2024-12-31T00:00:00.000Z + SNYK-JAVA-ORGBOUNCYCASTLE-6084022: + - '*': + reason: 'test-only dependency, no update available' + expires: 2024-12-31T00:00:00.000Z + SNYK-JAVA-ORGBOUNCYCASTLE-6277380: + - '*': + reason: 'test-only dependency, no update available' + expires: 2024-12-31T00:00:00.000Z + SNYK-JAVA-ORGBOUNCYCASTLE-6613080: + - '*': + reason: 'test-only dependency, no update available' + expires: 2024-12-31T00:00:00.000Z +patch: {} diff --git a/.version b/.version new file mode 100644 index 000000000..a5f3e61bd --- /dev/null +++ b/.version @@ -0,0 +1 @@ +2.27.0 diff --git a/CHANGELOG.md b/CHANGELOG.md index cce289260..8dc5a666b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,327 @@ # Change Log +## [2.27.0](https://github.com/auth0/auth0-java/tree/2.27.0) (2025-12-18) +[Full Changelog](https://github.com/auth0/auth0-java/compare/2.26.0...2.27.0) + +**Added** +- Feat: Add Google WorkSpace Provisioning Config Support [\#795](https://github.com/auth0/auth0-java/pull/795) ([tanya732](https://github.com/tanya732)) + +**Fixed** +- Fix: updated token_lifetime to Integer [\#797](https://github.com/auth0/auth0-java/pull/797) ([tanya732](https://github.com/tanya732)) + +## [2.26.0](https://github.com/auth0/auth0-java/tree/2.26.0) (2025-10-24) +[Full Changelog](https://github.com/auth0/auth0-java/compare/2.25.0...2.26.0) + +**Added** +- Adenix/client is token endpoint id header trusted [\#782](https://github.com/auth0/auth0-java/pull/782) ([tanya732](https://github.com/tanya732)) +- Feat: add constructor to set clientId on Client creation [\#781](https://github.com/auth0/auth0-java/pull/781) ([tanya732](https://github.com/tanya732)) + +## [2.25.0](https://github.com/auth0/auth0-java/tree/2.25.0) (2025-09-30) +[Full Changelog](https://github.com/auth0/auth0-java/compare/2.24.0...2.25.0) + +**Added** +- Added UserAttributeProfilePage and Deserializer [\#768](https://github.com/auth0/auth0-java/pull/768) ([tanya732](https://github.com/tanya732)) +- Added checkpoint pagination support for Connection Endpoint [\#767](https://github.com/auth0/auth0-java/pull/767) ([tanya732](https://github.com/tanya732)) +- Sdk 6843 self service provisioning java support [\#765](https://github.com/auth0/auth0-java/pull/765) ([tanya732](https://github.com/tanya732)) +- Support for patch clients credentials [\#760](https://github.com/auth0/auth0-java/pull/760) ([tanya732](https://github.com/tanya732)) + +**Fixed** +- Fix: URL Encodings [\#766](https://github.com/auth0/auth0-java/pull/766) ([tanya732](https://github.com/tanya732)) +- Fix: Updated to requested_expiry params [\#757](https://github.com/auth0/auth0-java/pull/757) ([tanya732](https://github.com/tanya732)) + +## [2.24.0](https://github.com/auth0/auth0-java/tree/2.24.0) (2025-08-22) +[Full Changelog](https://github.com/auth0/auth0-java/compare/2.23.0...2.24.0) + +**Added** +- Update Readme and Examples [\#752](https://github.com/auth0/auth0-java/pull/752) ([tanya732](https://github.com/tanya732)) +- Customize management api token provider [\#748](https://github.com/auth0/auth0-java/pull/748) ([tanya732](https://github.com/tanya732)) +- Joaosoumoreira/add method to enroll email mfa [\#744](https://github.com/auth0/auth0-java/pull/744) ([tanya732](https://github.com/tanya732)) + +## [2.23.0](https://github.com/auth0/auth0-java/tree/2.23.0) (2025-08-05) +[Full Changelog](https://github.com/auth0/auth0-java/compare/2.22.0...2.23.0) + +**Added** +- Added support for Tenant ACL [\#723](https://github.com/auth0/auth0-java/pull/723) ([tanya732](https://github.com/tanya732)) +- Added organization support for Change Password [\#726](https://github.com/auth0/auth0-java/pull/726) ([tanya732](https://github.com/tanya732)) +- Fix: Resource Server Scopes [\#725](https://github.com/auth0/auth0-java/pull/725) ([tanya732](https://github.com/tanya732)) + +## [2.22.0](https://github.com/auth0/auth0-java/tree/2.22.0) (2025-06-20) +[Full Changelog](https://github.com/auth0/auth0-java/compare/2.21.0...2.22.0) + +**Added** +- Added support for connectionKeys Endpoint [\#721](https://github.com/auth0/auth0-java/pull/721) ([tanya732](https://github.com/tanya732)) + +## [2.21.0](https://github.com/auth0/auth0-java/tree/2.21.0) (2025-05-30) +[Full Changelog](https://github.com/auth0/auth0-java/compare/2.20.0...2.21.0) + +**Added** +- SDK Limit M2M Java Support [\#708](https://github.com/auth0/auth0-java/pull/708) ([tanya732](https://github.com/tanya732)) +- Added support for GET/PATCH Connection Endpoints [\#718](https://github.com/auth0/auth0-java/pull/718) ([tanya732](https://github.com/tanya732)) +- Added support for EmailTemplate [\#720](https://github.com/auth0/auth0-java/pull/720) ([tanya732](https://github.com/tanya732)) + +**Fixed** +- Updated EnabledConnection [\#719](https://github.com/auth0/auth0-java/pull/719) ([tanya732](https://github.com/tanya732)) + +## [2.20.0](https://github.com/auth0/auth0-java/tree/2.20.0) (2025-05-06) +[Full Changelog](https://github.com/auth0/auth0-java/compare/2.19.0...2.20.0) + +**Fixed** +- Fixed POST/PATCH connection endpoints [\#710](https://github.com/auth0/auth0-java/pull/710) ([tanya732](https://github.com/tanya732)) +- Fix log event [\#711](https://github.com/auth0/auth0-java/pull/711) ([tanya732](https://github.com/tanya732)) + +## [2.19.0](https://github.com/auth0/auth0-java/tree/2.19.0) (2025-03-28) +[Full Changelog](https://github.com/auth0/auth0-java/compare/2.18.0...2.19.0) + +**Added** +- Added support for SSO-FF [\#702](https://github.com/auth0/auth0-java/pull/702) ([tanya732](https://github.com/tanya732)) +- Check point pagination support for get connection [\#704](https://github.com/auth0/auth0-java/pull/704) ([tanya732](https://github.com/tanya732)) + +## [2.18.0](https://github.com/auth0/auth0-java/tree/2.18.0) (2025-02-19) +[Full Changelog](https://github.com/auth0/auth0-java/compare/2.17.0...2.18.0) + +**Added** +- Added missing fields in LogEventClass [\#698](https://github.com/auth0/auth0-java/pull/698) ([tanya732](https://github.com/tanya732)) +- Added support for revoke session endpoint [\#699](https://github.com/auth0/auth0-java/pull/699) ([tanya732](https://github.com/tanya732)) +- Added Connection's SCIM Server Support [\#696](https://github.com/auth0/auth0-java/pull/696) ([tanya732](https://github.com/tanya732)) + +## [2.17.0](https://github.com/auth0/auth0-java/tree/2.17.0) (2025-01-10) +[Full Changelog](https://github.com/auth0/auth0-java/compare/2.16.0...2.17.0) + +**Added** +- Update EXAMPLES.md to fix variable usage [\#690](https://github.com/auth0/auth0-java/pull/690) ([tanya732](https://github.com/tanya732)) +- Added Support for Self-Service-Profile [\#683](https://github.com/auth0/auth0-java/pull/683) ([tanya732](https://github.com/tanya732)) +- Added support for Back Channel Login [\#682](https://github.com/auth0/auth0-java/pull/682) ([tanya732](https://github.com/tanya732)) + +## [2.17.0](https://github.com/auth0/auth0-java/tree/2.17.0) (2025-01-08) +[Full Changelog](https://github.com/auth0/auth0-java/compare/2.16.0...2.17.0) + +**Added** +- Update EXAMPLES.md to fix variable usage [\#690](https://github.com/auth0/auth0-java/pull/690) ([tanya732](https://github.com/tanya732)) +- Added Support for Self-Service-Profile [\#683](https://github.com/auth0/auth0-java/pull/683) ([tanya732](https://github.com/tanya732)) +- Added support for Back Channel Login [\#682](https://github.com/auth0/auth0-java/pull/682) ([tanya732](https://github.com/tanya732)) + +## [2.16.0](https://github.com/auth0/auth0-java/tree/2.16.0) (2024-12-03) +[Full Changelog](https://github.com/auth0/auth0-java/compare/2.15.0...2.16.0) + +**Added** +- Added support for custom prompts [\#680](https://github.com/auth0/auth0-java/pull/680) ([tanya732](https://github.com/tanya732)) +- Added phone number identifier in signup Auth API [\#679](https://github.com/auth0/auth0-java/pull/679) ([tanya732](https://github.com/tanya732)) +- Added is_signup_enabled field to OrganizationConnection [\#677](https://github.com/auth0/auth0-java/pull/677) ([tanya732](https://github.com/tanya732)) + +## [2.15.0](https://github.com/auth0/auth0-java/tree/2.15.0) (2024-10-31) +[Full Changelog](https://github.com/auth0/auth0-java/compare/2.14.0...2.15.0) + +**Added** +- Added support for byok [\#673](https://github.com/auth0/auth0-java/pull/673) ([tanya732](https://github.com/tanya732)) + +## [2.14.0](https://github.com/auth0/auth0-java/tree/2.14.0) (2024-10-16) +[Full Changelog](https://github.com/auth0/auth0-java/compare/2.13.0...2.14.0) + +**Added** +- SDKs support for Control Your Own Key [\#671](https://github.com/auth0/auth0-java/pull/671) ([tanya732](https://github.com/tanya732)) +- Added client credentials changes [\#670](https://github.com/auth0/auth0-java/pull/670) ([tanya732](https://github.com/tanya732)) +- Added support for HRI phase 2 changes [\#668](https://github.com/auth0/auth0-java/pull/668) ([tanya732](https://github.com/tanya732)) + +## [2.13.0](https://github.com/auth0/auth0-java/tree/2.13.0) (2024-09-11) +[Full Changelog](https://github.com/auth0/auth0-java/compare/2.12.0...2.13.0) + +**Added** +- Add sessions and refresh tokens to Users Management API [\#661](https://github.com/auth0/auth0-java/pull/661) ([tanya732](https://github.com/tanya732)) + +## [2.12.0](https://github.com/auth0/auth0-java/tree/2.12.0) (2024-05-29) +[Full Changelog](https://github.com/auth0/auth0-java/compare/2.11.0...2.12.0) + +**Added** +- Support delete all authentication methods endpoint [\#645](https://github.com/auth0/auth0-java/pull/645) ([jimmyjames](https://github.com/jimmyjames)) + +## [2.11.0](https://github.com/auth0/auth0-java/tree/2.11.0) (2024-04-29) +[Full Changelog](https://github.com/auth0/auth0-java/compare/2.10.1...2.11.0) + +**Added** +- [SDK-4763] - RIch Authorization Request (RAR) [\#637](https://github.com/auth0/auth0-java/pull/637) ([jimmyjames](https://github.com/jimmyjames)) +- [SDK-4763] - Add support for HRI Management API changes [\#635](https://github.com/auth0/auth0-java/pull/635) ([jimmyjames](https://github.com/jimmyjames)) +- [SDK-4763] - add support for JAR and PAR with JAR to Authentication API [\#636](https://github.com/auth0/auth0-java/pull/636) ([jimmyjames](https://github.com/jimmyjames)) +- [SDK-4769] - add show_as_button to Organization Enabled Connections [\#631](https://github.com/auth0/auth0-java/pull/631) ([jimmyjames](https://github.com/jimmyjames)) + +## [2.10.1](https://github.com/auth0/auth0-java/tree/2.10.1) (2024-01-29) +[Full Changelog](https://github.com/auth0/auth0-java/compare/2.10.0...2.10.1) + +**Deprecated** +- Organizations API no longer returns enabled_connections [\#604](https://github.com/auth0/auth0-java/pull/604) ([jimmyjames](https://github.com/jimmyjames)) + +# [2.10.0](https://github.com/auth0/auth0-java/tree/2.10.0) (2023-12-15) +[Full Changelog](https://github.com/auth0/auth0-java/compare/2.9.0...2.10.0) + +**Added** +- support backchannel logout property on Client [\#587](https://github.com/auth0/auth0-java/pull/587) ([jimmyjames](https://github.com/jimmyjames)) + +# [2.9.0](https://github.com/auth0/auth0-java/tree/2.9.0) (2023-11-21) +[Full Changelog](https://github.com/auth0/auth0-java/compare/2.8.0...2.9.0) + +**Added** +- Support organization in client credentials [\#582](https://github.com/auth0/auth0-java/pull/582) ([jimmyjames](https://github.com/jimmyjames)) + +# [2.8.0](https://github.com/auth0/auth0-java/tree/2.8.0) (2023-11-07) +[Full Changelog](https://github.com/auth0/auth0-java/compare/2.7.0...2.8.0) + +**Fixed** +- Propagate error messages on rate limit exceptions [\#579](https://github.com/auth0/auth0-java/pull/579) ([jimmyjames](https://github.com/jimmyjames)) + +## [2.7.0](https://github.com/auth0/auth0-java/tree/2.7.0) (2023-10-31) +[Full Changelog](https://github.com/auth0/auth0-java/compare/2.6.1...2.7.0) + +**Added** +- Support organization get member roles [\#574](https://github.com/auth0/auth0-java/pull/574) ([jimmyjames](https://github.com/jimmyjames)) +- Add passkey properties to authentication method response [\#575](https://github.com/auth0/auth0-java/pull/575) ([jimmyjames](https://github.com/jimmyjames)) + +## [2.6.1](https://github.com/auth0/auth0-java/tree/2.6.1) (2023-09-22) +[Full Changelog](https://github.com/auth0/auth0-java/compare/2.6.0...2.6.1) + +**Security** +- Update Okio to resolve CVE-2023-3635 [\#560](https://github.com/auth0/auth0-java/pull/560) ([evansims](https://github.com/evansims)) + +## [2.6.0](https://github.com/auth0/auth0-java/tree/2.6.0) (2023-09-07) +[Full Changelog](https://github.com/auth0/auth0-java/compare/2.5.0...2.6.0) + +**Security** +- Update OkHttp to 4.11.0 [\#558](https://github.com/auth0/auth0-java/pull/558) ([evansims](https://github.com/evansims)) + +**Fixed** +- Align json property 'cross_origin_authentication' with api docs [\#555](https://github.com/auth0/auth0-java/pull/555) ([Jojo134](https://github.com/Jojo134)) + +## [2.5.0](https://github.com/auth0/auth0-java/tree/2.5.0) (2023-07-18) +[Full Changelog](https://github.com/auth0/auth0-java/compare/2.4.0...2.5.0) + +**Added** +- Support Organization Name on Authorize URL [\#550](https://github.com/auth0/auth0-java/pull/550) ([vasantteja](https://github.com/vasantteja)) + +**Fixed** +- Fix deleteAuthenticationMethodById [\#552](https://github.com/auth0/auth0-java/pull/552) ([jimmyjames](https://github.com/jimmyjames)) + +## [2.4.0](https://github.com/auth0/auth0-java/tree/2.4.0) (2023-06-15) +[Full Changelog](https://github.com/auth0/auth0-java/compare/2.3.0...2.4.0) + +**Added** +- Support delete authenticator endpoint [\#541](https://github.com/auth0/auth0-java/pull/541) ([vasantteja](https://github.com/vasantteja)) +- Support invalidate remembered browsers endpoint [\#543](https://github.com/auth0/auth0-java/pull/543) ([jimmyjames](https://github.com/jimmyjames)) + +**Fixed** +- Export users does not require connection_id [\#537](https://github.com/auth0/auth0-java/pull/537) ([jimmyjames](https://github.com/jimmyjames)) + +## [2.3.0](https://github.com/auth0/auth0-java/tree/2.3.0) (2023-05-11) +[Full Changelog](https://github.com/auth0/auth0-java/compare/2.2.0...2.3.0) + +**Added** +- Support Pushed Authorization Requests [\#534](https://github.com/auth0/auth0-java/pull/534) ([jimmyjames](https://github.com/jimmyjames)) + +## [2.2.0](https://github.com/auth0/auth0-java/tree/2.2.0) (2023-05-02) +[Full Changelog](https://github.com/auth0/auth0-java/compare/2.1.0...2.2.0) + +**Added** +- Add support for client credential management [\#525](https://github.com/auth0/auth0-java/pull/525) ([jimmyjames](https://github.com/jimmyjames)) + +**Fixed** +- Fix headers to lowercase [\#528](https://github.com/auth0/auth0-java/pull/528) ([alexz75](https://github.com/alexz75)) + + +## [2.1.0](https://github.com/auth0/auth0-java/tree/2.1.0) (2023-03-31) +[Full Changelog](https://github.com/auth0/auth0-java/compare/2.0.0...2.1.0) + +**Added** +- Add missing LogEvent fields [\#521](https://github.com/auth0/auth0-java/pull/521) ([jimmyjames](https://github.com/jimmyjames)) + +**Changed** +- authentication_methods is an object, not a string [\#520](https://github.com/auth0/auth0-java/pull/520) ([jimmyjames](https://github.com/jimmyjames)) +- Bump jackson dependency to 2.14.2 [\#522](https://github.com/auth0/auth0-java/pull/522) ([jimmyjames](https://github.com/jimmyjames)) +- Update java-jwt dependency to 4.4.0 [\#523](https://github.com/auth0/auth0-java/pull/523) ([jimmyjames](https://github.com/jimmyjames)) + +## [2.0.0](https://github.com/auth0/auth0-java/tree/2.0.0) (2023-02-23) +[Full Changelog](https://github.com/auth0/auth0-java/compare/1.44.2...2.0.0) + +2.0.0 introduces several enhances, including: +- HTTP response information returned from requests +- Additional HTTP client configurability +- Ability to configure requests such as add additional parameters and headers +- Support for Authentication API MFA-related APIs +- Authentication API improvements to not require a client secret +- ... and more! + +As a major version release, 2.0.0 does include breaking changes. +Please see the [Migration Guide](MIGRATION_GUIDE.md) for additional details as well as guidance for updating your application. + +## [2.0.0 Beta 2](https://github.com/auth0/auth0-java/tree/2.0.0-beta.2) (2023-02-13) +[Full Changelog](https://github.com/auth0/auth0-java/compare/2.0.0-beta.1...2.0.0-beta.2) + +**Changed** +- Update to latest java-jwt version [\#512](https://github.com/auth0/auth0-java/pull/512) ([jimmyjames](https://github.com/jimmyjames)) + +## [2.0.0 Beta 1](https://github.com/auth0/auth0-java/tree/2.0.0-beta.1) (2023-01-26) +[Full Changelog](https://github.com/auth0/auth0-java/compare/2.0.0-beta.0...2.0.0-beta.1) + +**Added** +- Add support for MFA APIs [\#505](https://github.com/auth0/auth0-java/pull/505) ([poovamraj](https://github.com/poovamraj)) +- Add support MFA Methods API [\#506](https://github.com/auth0/auth0-java/pull/506) ([poovamraj](https://github.com/poovamraj)) +- Support JWT Client Authentication [\#507](https://github.com/auth0/auth0-java/pull/507) ([jimmyjames](https://github.com/jimmyjames)) + +## [2.0.0 Beta 0](https://github.com/auth0/auth0-java/tree/2.0.0-beta.0) (2023-01-12) +[Full Changelog](https://github.com/auth0/auth0-java/compare/1.44.2...2.0.0-beta.0) + +> **Warning** This SDK is in beta and is subject to breaking changes. It is not recommended for production use, but your feedback and help in testing is appreciated! + +This release introduces several enhancement, including: +- HTTP response information returned from requests +- Additional HTTP client configurability +- Authentication API improvements to not require a client secret +- ... and more! + +Please see the [Migration Guide](MIGRATION_GUIDE.md) for guidance on updating your application. + +## [1.44.2](https://github.com/auth0/auth0-java/tree/1.44.2) (2023-01-11) +[Full Changelog](https://github.com/auth0/auth0-java/compare/1.44.1...1.44.2) + +This patch release does not contain any functional changes, but is being released using an updated signing key for verification as part of our commitment to best security practices. +Please review [the README note for additional details.](https://github.com/auth0/auth0-java/blob/master/README.md) + +**Security** +- Bump java-jwt dependency to 3.19.4 [\#498](https://github.com/auth0/auth0-java/pull/498) ([jimmyjames](https://github.com/jimmyjames)) + +## [1.44.1](https://github.com/auth0/auth0-java/tree/1.44.1) (2022-10-25) +[Full Changelog](https://github.com/auth0/auth0-java/compare/1.44.0...1.44.1) + +**Security** +- Bump `java-jwt` to 3.19.3 [\#465](https://github.com/auth0/auth0-java/pull/465) ([jimmyjames](https://github.com/jimmyjames)) +- Bump `com.fasterxml.jackson.core:jackson-databind` to 2.13.4.2 [\#464](https://github.com/auth0/auth0-java/pull/464) ([evansims](https://github.com/evansims)) + +## [1.44.0](https://github.com/auth0/auth0-java/tree/1.44.0) (2022-10-20) +[Full Changelog](https://github.com/auth0/auth0-java/compare/1.43.0...1.44.0) + +**Added** +- Integrate ship orb [\#458](https://github.com/auth0/auth0-java/pull/458) ([jimmyjames](https://github.com/jimmyjames)) +- [SDK-2558] Add support for tenant session cookie [\#457](https://github.com/auth0/auth0-java/pull/457) ([jimmyjames](https://github.com/jimmyjames)) +- Support stage property on Breached Password Detection [\#456](https://github.com/auth0/auth0-java/pull/456) ([ewanharris](https://github.com/ewanharris)) + +**Changed** +- Update to Gradle 6.9.2 [\#455](https://github.com/auth0/auth0-java/pull/455) ([jimmyjames](https://github.com/jimmyjames)) + +## [1.43.0](https://github.com/auth0/auth0-java/tree/1.43.0) (2022-09-19) +[Full Changelog](https://github.com/auth0/auth0-java/compare/1.42.0...1.43.0) + +**Added** +- Add support for deleting all user's authenticators [\#451](https://github.com/auth0/auth0-java/pull/451) ([jimmyjames](https://github.com/jimmyjames)) +- Add session idle lifetime and make session lifetime doubles [\#423](https://github.com/auth0/auth0-java/pull/423) ([pelletier197](https://github.com/pelletier197)) +- #448 Adding field filter option to get client by ID API [\#449](https://github.com/auth0/auth0-java/pull/449) ([bhatmadhavi](https://github.com/bhatmadhavi)) +- Add missing fields in Client model [\#444](https://github.com/auth0/auth0-java/pull/444) ([poovamraj](https://github.com/poovamraj)) +- Add Ship CLI configuration [\#433](https://github.com/auth0/auth0-java/pull/433) ([frederikprijck](https://github.com/frederikprijck)) + +**Changed** +- Update to OSS plugin version 0.17.2 [\#450](https://github.com/auth0/auth0-java/pull/450) ([jimmyjames](https://github.com/jimmyjames)) +- Bump oss-library and auth0/ship [\#441](https://github.com/auth0/auth0-java/pull/441) ([frederikprijck](https://github.com/frederikprijck)) +- Ensure version is defined before plugins are applied [\#439](https://github.com/auth0/auth0-java/pull/439) ([frederikprijck](https://github.com/frederikprijck)) + +**Security** +- Replace Codecov uploader w/ CircleCI Orb [\#446](https://github.com/auth0/auth0-java/pull/446) ([evansims](https://github.com/evansims)) +- Security: Update OkHttp to 4.10.0 [\#438](https://github.com/auth0/auth0-java/pull/438) ([evansims](https://github.com/evansims)) + ## [1.42.0](https://github.com/auth0/auth0-java/tree/1.42.0) (2022-05-20) [Full Changelog](https://github.com/auth0/auth0-java/compare/1.41.0...1.42.0) diff --git a/EXAMPLES.md b/EXAMPLES.md new file mode 100644 index 000000000..e599e0108 --- /dev/null +++ b/EXAMPLES.md @@ -0,0 +1,208 @@ +# Examples using auth0-java + +- [Error handling](#error-handling) +- [HTTP Client configuration](#http-client-configuration) +- [Verifying an ID token](#verifying-an-id-token) +- [Organizations](#organizations) +- [Client credential management](#client-credential-management) +- [Asynchronous operations](#asynchronous-operations) + +## Error handling + +The API Clients throw an `Auth0Exception` when an unexpected error happens on a request execution, for example a connection or timeout error. + +An `APIException` will be thrown if the network request succeeded, but another error occurred. + +```java +Request request = api.users().list(new UserFilter().withSearchEngine("v1")); +try { + UsersPage usersPage = request.execute().getBody(); +} catch(APIException apiException) { + apiException.getStatusCode(); // 400 + apiException.getError(); // "operation_not_supported" + apiException.getDescription(); // "You are not allowed to use search_engine=v1." +} +``` + +## HTTP Client configuration + +By default, both the Authentication and Management API clients use the OkHttp networking library to make HTTP requests. +The client can be configured by building a `DefaultHttpClient` and providing it to the API clients. +If using both the Management and Authentication API clients, it is recommended to create one `Auth0HttpClient` to be used by both API clients to minimize resource usage. + +```java +Auth0HttpClient client = DefaultHttpClient.newBuilder() + // configure as needed + .build(); + +AuthAPI auth = AuthAPI.newBuilder("DOMAIN", "CLIENT-ID", "CLIENT-SECRET") + .withHttpClient(client) + .build(); + +``` + +```java + +ManagementAPI mgmt = ManagementAPI.newBuilder("DOMAIN", "API-TOKEN") + .withHttpClient(client) + .build(); + +// OR + +TokenProvider tokenProvider = SimpleTokenProvider.create("API-TOKEN"); + +ManagementAPI mgmt = ManagementAPI.newBuilder("DOMAIN", tokenProvider) + .withHttpClient(client) + .build(); + +``` + +If the `DefaultHttpClient` does not support your required networking client configuration, you may choose to implement +your own client by implementing the `Auth0HttpClient` interface and providing it to the API clients. This is an advanced +use case and should be used only when necessary. + +## Verifying an ID token + +This library also provides the ability to validate an OIDC-compliant ID Token, according to the [OIDC Specification](https://openid.net/specs/openid-connect-core-1_0-final.html#IDTokenValidation). + +### Verifying an ID Token signed with the RS256 signing algorithm + +To verify an ID Token that is signed using the RS256 signing algorithm, you will need to provide an implementation of +`PublicKeyProvider` that will return the public key used to verify the token's signature. The example below demonstrates how to use the `JwkProvider` from the [jwks-rsa-java](https://github.com/auth0/jwks-rsa-java) library: + +```java +JwkProvider provider = new JwkProviderBuilder("https://your-domain.auth0.com").build(); +SignatureVerifier signatureVerifier = SignatureVerifier.forRS256(new PublicKeyProvider() { + @Override + public RSAPublicKey getPublicKeyById(String keyId) throws PublicKeyProviderException { + try { + return (RSAPublicKey) provider.get(keyId).getPublicKey(); + } catch (JwkException jwke) { + throw new PublicKeyProviderException("Error obtaining public key", jwke); + } + } +} + +IdTokenVerifier idTokenVerifier = IdTokenVerifier.init("https://your-domain.auth0.com/","your-client-id", signatureVerifier).build(); + +try { + idTokenVerifier.verify("token", "expected-nonce"); +} catch(IdTokenValidationException idtve) { + // Handle invalid token exception +} +``` + +### Verifying an ID Token signed with the HS256 signing algorithm + +To verify an ID Token that is signed using the HS256 signing algorithm: + +```java +SignatureVerifier signatureVerifier = SignatureVerifier.forHS256("your-client-secret"); +IdTokenVerifier idTokenVerifier = IdTokenVerifier.init("https://your-domain.auth0.com/","your-client-id", signatureVerifier).build(); + +try { + idTokenVerifier.verify("token", "expected-nonce"); +} catch(IdTokenValidationException idtve) { + // Handle invalid token exception +} +``` + +## Organizations + +[Organizations](https://auth0.com/docs/organizations) is a set of features that provide better support for developers who build and maintain SaaS and Business-to-Business (B2B) applications. + +Note that Organizations is currently only available to customers on our Enterprise and Startup subscription plans. + +### Log in to an organization + +Log in to an organization by using `withOrganization()` when building the Authorization URL: + +```java +AuthAPI auth = AuthAPI.newBuilder("{YOUR_DOMAIN}", "{YOUR_CLIENT_ID}", "{YOUR_CLIENT_SECRET}").build(); +String url = auth.authorizeUrl("https://me.auth0.com/callback") + .withOrganization("{YOUR_ORGANIZATION_ID") + .build(); +``` + +**Important!** When logging into an organization, it is important to ensure the `org_id` claim of the ID Token matches the expected organization value. The `IdTokenVerifier` can be configured with an expected `org_id` claim value, as the example below demonstrates. +For more information, please read [Work with Tokens and Organizations](https://auth0.com/docs/organizations/using-tokens) on Auth0 Docs. +```java +IdTokenVerifier.init("{ISSUER}", "{AUDIENCE}", signatureVerifier) + .withOrganization("{ORG_ID}") + .build() + .verify(jwt); +``` + +### Accept user invitations + +Accept a user invitation by using `withInvitation()` when building the Authorization URL: + +``` +AuthAPI auth = AuthAPI.newBuilder("{YOUR_DOMAIN}", "{YOUR_CLIENT_ID}", "{YOUR_CLIENT_SECRET}").build(); +String url = auth.authorizeUrl("https://me.auth0.com/callback") + .withOrganization("{YOUR_ORGANIZATION_ID") + .withInvitation("{YOUR_INVITATION_ID}") + .build(); +``` + +## Client credential management + +The SDK provides comprehensive support for managing client credentials used for machine-to-machine authentication and API access. + +### List client credentials + +```java +ManagementAPI mgmt = ManagementAPI.newBuilder("{YOUR_DOMAIN}", "{YOUR_API_TOKEN}").build(); +Request> request = mgmt.clients().listCredentials("{CLIENT_ID}"); +List credentials = request.execute().getBody(); +``` + +### Get a specific client credential + +```java +Request request = mgmt.clients().getCredential("{CLIENT_ID}", "{CREDENTIAL_ID}"); +Credential credential = request.execute().getBody(); +``` + +### Create a new client credential + +```java +Credential newCredential = new Credential("public_key", "{PEM_CONTENT}"); +newCredential.setName("My API Credential"); +Request request = mgmt.clients().createCredential("{CLIENT_ID}", newCredential); +Credential createdCredential = request.execute().getBody(); +``` + +### Update an existing client credential + +```java +Credential updates = new Credential(); +updates.setExpiresAt(""); +// Note: expires_at can also be updated by setting a Date object +Request request = mgmt.clients().updateCredential("{CLIENT_ID}", "{CREDENTIAL_ID}", updates); +Credential updatedCredential = request.execute().getBody(); +``` + +### Delete a client credential + +```java +Request request = mgmt.clients().deleteCredential("{CLIENT_ID}", "{CREDENTIAL_ID}"); +request.execute(); +``` + +**Required Scopes**: +- `read:client_credentials` - for listing and getting credentials +- `create:client_credentials` - for creating new credentials +- `update:client_credentials` - for updating existing credentials +- `delete:client_credentials` - for deleting credentials + +For more information, see the [Auth0 Management API documentation](https://auth0.com/docs/api/management/v2/clients). + +## Asynchronous operations + +Requests can be executed asynchronously, using the `executeAsync()` method, which returns a `CompletableFuture`. + +```java +CompletableFuture> userFuture = mgmt.users().getUser("auth0|123", new UserFilter()).executeAsync(); +User user = userFuture.get().getBody(); +``` diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md new file mode 100644 index 000000000..5327386a6 --- /dev/null +++ b/MIGRATION_GUIDE.md @@ -0,0 +1,154 @@ +# Migration Guide + +## Migrating from v1 to v2 + +The version 2 release includes several notable improvements, including: + +* Requests can now be configured with additional parameters and headers, without needing to downcast to `CustomRequest`. +* Responses are now wrapped in a new `com.auth0.net.Response` type, which provides information about the HTTP response such as headers and status code. +* The `AuthAPI` and `ManagementAPI` clients can now share the same HTTP client. +* The `AuthAPI` client no longer requires a client secret, enabling support for APIs and scenarios where a secret is not required. + +Version 2 includes breaking changes. Please read this guide to learn how to update your application for v2. + +### Configuring `auth0-java` v2 + +To create the API clients, use the new builders, and specify any HTTP-related configurations with the new `DefaultHttpClient`: + +```java +Auth0HttpClient http = DefaultHttpClient.newBuilder() + .withConnectTimeout(10) + .withReadTimeout(10) + // additional configurations as needed + .build(); + +AuthAPI auth = AuthAPI.newBuilder("{DOMAIN}", "{CLIENT-ID}", "{OPTIONAL-CLIENT-SECRET}") + .withHttpClient(http) + .build(); + +ManagementAPI mgmt = ManagementAPI.newBuilder("{DOMAIN}", "{API-TOKEN}") + .withHttpClient(http) + .build(); +``` + +### Response information + +Version 2 returns HTTP response information such as status code and headers in a new `com.auth0.net.Response` type. +Instead of simply returning the parsed JSON response body from requests, all API methods now return a `Response`. +If you have no need for the response information, replace any calls to `execute()` with `execute().getBody()` to get the returned response body as before: + +```java +// Get response info +Response userResponse = api.users().get("{USER-ID}", null); +int code = userResponse.getStatusCode(); +Map headers = userResponse.getHeaders(); + +// Just get the response body +User user = api.users().get("{USER-ID}", null).execute().getBody(); +``` + +### Request configuration + +Previously, only requests that returned a `CustomizableRequest` (or its implementation, `CustomRequest`) allowed for a request to be configured with additional parameters or headers. +In v2, the `com.auth0.net.Request` interface defines the new methods: + +- `Request addHeader(String name, String value)` +- `Request addParameter(String name, Object value)` +- `Request setBody(Object body)` + +This enables all requests to be configured, without the need to downcast to `CustomizableRequest` or `CustomRequest`. +If you were down-casting to these types, you will need to remove the cast and instead configure the request directly: + +```java +Request userRequest = api.users().get("{USER-ID}", null); +userRequest.addHeader("some-header", "some-value"); +Response userResponse = userRequest.execute(); +``` + +### Detailed changes + +The following summarizes details of the changes in version 2, including types and methods removed, added, or deprecated. + +#### Removed classes + +- `AuthRequest` has been removed. Use `TokenRequest` instead. +- `CustomizableRequest` and `CustomRequest` have been removed. The `Request` interface now supports request customization directly without the need to downcast. +- `FormDataRequest` has been removed. Use `MultipartRequest` instead. +- `CreateUserRequest` has been removed. Use `SignUpRequest` instead. + +#### Moved classes + +- `com.auth0.json.mgmt.Token` moved to `com.auth0.json.mgmt.blacklists.Token` +- `com.auth0.json.mgmt.ClientGrant` moved to `com.auth0.json.mgmt.clientgrants.ClientGrant` +- `com.auth0.json.mgmt.ClientGrantsPage` moved to `com.auth0.json.mgmt.clientgrants.ClientGrantsPage` +- `com.auth0.json.mgmt.Connection` moved to `com.auth0.json.mgmt.connections.Connection` +- `com.auth0.json.mgmt.ConnectionsPage` moved to `com.auth0.json.mgmt.connections.ConnectionsPage` +- `com.auth0.json.mgmt.DeviceCredentials` moved to `com.auth0.json.mgmt.devicecredentials.DeviceCredentials` +- `com.auth0.json.mgmt.EmailTemplate` moved to `com.auth0.json.mgmt.emailtemplates.EmailTemplate` +- `com.auth0.json.mgmt.Grant` moved to `com.auth0.json.mgmt.grants.Grant` +- `com.auth0.json.mgmt.GrantsPage` moved to `com.auth0.json.mgmt.grants.GrantsPage` +- `com.auth0.json.mgmt.EmailVerificationIdentity` moved to `com.auth0.json.mgmt.tickets.EmailVerificationIdentity` +- `com.auth0.json.mgmt.Key;` moved to `com.auth0.json.mgmt.keys.Key` +- `com.auth0.json.mgmt.RolesPage` moved to `com.auth0.json.mgmt.roles.RolesPage` +- `com.auth0.json.mgmt.ResourceServer` moved to `com.auth0.json.mgmt.resourceserver.ResourceServer` +- `com.auth0.json.mgmt.ResourceServersPage` moved to `com.auth0.json.mgmt.resourceserver.ResourceServersPage` +- `com.auth0.json.mgmt.Permission` moved to `com.auth0.json.mgmt.permissions.Permission` +- `com.auth0.json.mgmt.PermissionsPage` moved to `com.auth0.json.mgmt.permissions.PermissionsPage` +- `com.auth0.json.mgmt.Role` moved to `com.auth0.json.mgmt.roles.Role` +- `com.auth0.json.mgmt.RolesPage` moved to `com.auth0.json.mgmt.roles.RolesPage` +- `com.auth0.json.mgmt.RulesConfig` moved to `com.auth0.json.mgmt.rules.RulesConfig` +- `com.auth0.json.mgmt.Rule` moved to `com.auth0.json.mgmt.rules.Rule` +- `com.auth0.json.mgmt.RulesPage` moved to `com.auth0.json.mgmt.rules.RulesPage` +- `com.auth0.json.mgmt.DailyStats` moved to `com.auth0.json.mgmt.stats.DailyStats` +- `com.auth0.json.mgmt.Permission` moved to `com.auth0.json.mgmt.permissions.Permission` +- `com.auth0.json.mgmt.PermissionsPage` moved to `com.auth0.json.mgmt.permissions.PermissionsPage` +- `com.auth0.json.mgmt.RolesPage` moved to `com.auth0.json.mgmt.roles.RolesPage` + +#### Removed methods + +- `void com.auth0.client.mgmt.ManagementAPI#doNotSendTelemetry()` has been removed. Telemetry configuration can be done using the `DefaultHttpClient#Builder` +- `void com.auth0.client.auth.AuthAPI#doNotSendTelemetry()` has been removed. Telemetry configuration can be done using the `DefaultHttpClient#Builder` +- `void com.auth0.client.mgmt.ManagementAPI#setTelemetry(Telemetry telemetry)` has been removed. Telemetry configuration can be done using the `DefaultHttpClient#Builder` +- `void com.auth0.client.auth.AuthAP#setTelemetry(Telemetry telemetry)` has been removed. Telemetry configuration can be done using the `DefaultHttpClient#Builder` +- Deprecated `void com.auth0.client.mgmt.ManagementAPI#setLoggingEnabled(boolean enabled)` has been removed. Telemetry configuration can be done using the `DefaultHttpClient#Builder` +- Deprecated `void com.auth0.client.auth.AuthAPI#setLoggingEnabled(boolean enabled)` has been removed. Telemetry configuration can be done using the `DefaultHttpClient#Builder` +- Deprecated `Request> com.auth0.client.mgmt.ClientGrantsEntity#list()` has been removed. Use `Request list(ClientGrantsFilter filter) com.auth0.client.mgmt.ClientGrantsEntity#list(ClientGrantsFilter filter)` instead. +- Deprecated `Request> com.auth0.client.mgmt.ClientsEntity#list()` has been removed. Use `Request com.auth0.client.mgmt.ClientsEntity#list(ClientFilter filter)` instead. +- Deprecated `Request> com.auth0.client.mgmt.ClientsEntity#list(ConnectionFilter filter)` has been removed. Use `Request com.auth0.client.mgmt.ClientsEntity#listAll(ConnectionFilter filter)` instead. +- Deprecated `Request> com.auth0.client.mgmt.GrantsEntity#list(String userId)` has been removed. Use `Request com.auth0.client.mgmt.GrantsEntity#list(String userId, GrantsFilter filter)` instead. +- Deprecated `Request> com.auth0.client.mgmt.ResourceServerEntity#list()` has been removed. Use `Request com.auth0.client.mgmt.ResourceServersEntity#list(ResourceServersFilter)` instead. +- Deprecated `Request> com.auth0.client.mgmt.RulesEntity#list(RulesFilter filter)` has been removed. Use `Request com.auth0.client.mgmt.RulesEntity#listAll(RulesFilter filter)` instead. +- Deprecated `void com.auth0.json.mgmt.guardian.EnrollmentTicket#setUserId(String id)` has been removed. Use the constructor instead. +- Deprecated `com.auth0.json.mgmt.guardian.SNSFactorProvider` no-arg constructor has been removed. Use the full constructor instead. +- Deprecated `void com.auth0.json.mgmt.guardian.SNSFactorProvider#setAWSAccessKeyId(String awsAccessKeyId)` has been removed. Use the constructor instead. +- Deprecated `void com.auth0.json.mgmt.guardian.SNSFactorProvider#setAWSSecretAccessKey(String awsSecretAccessKey)` has been removed. Use the constructor instead. +- Deprecated `void com.auth0.json.mgmt.guardian.SNSFactorProvider#setAWSRegion(String awsRegion)` has been removed. Use the constructor instead. +- Deprecated `void com.auth0.json.mgmt.guardian.SNSFactorProvider#setSNSAPNSPlatformApplicationARN(String apnARN)` has been removed. Use the constructor instead. +- Deprecated `void com.auth0.json.mgmt.guardian.SNSFactorProvider#setSNSGCMPlatformApplicationARN(String gcmARN)` has been removed. Use the constructor instead. +- Deprecated `com.auth0.json.mgmt.guardian.TwilioFactorProvider` no-arg constructor has been removed. Use the full constructor instead. +- Deprecated `void com.auth0.json.mgmt.guardian.TwilioFactorProvider#setFrom(String from)` has been removed. Use the constructor instead. +- Deprecated `void com.auth0.json.mgmt.guardian.TwilioFactorProvider#setMessagingServiceSID(String messagingServiceSID)` has been removed. Use the constructor instead. +- Deprecated `void com.auth0.json.mgmt.guardian.TwilioFactorProvider#setAuthToken(String authToken)` has been removed. Use the constructor instead. +- Deprecated `void com.auth0.json.mgmt.guardian.TwilioFactorProvider#setSID(String SID)` has been removed. Use the constructor instead. +- The default implementation of `com.auth0.net.Request#executeAsync()` has been removed; implementations must provide an implementation of `executeAsync`. + +### New classes and methods + +#### Refactored HTTP layer types + +Version 2 introduces a new abstraction, `com.auth0.net.client.Auth0HttpClient`, to handle the core HTTP responsibilities of sending HTTP requests. +An implementation is provided in `DefaultHttpClient`, which supports all the configurations available in the now-deprecated `HttpOptions`. +In addition to these configurations, it is also possible to implement the `Auth0HttpClient` for advanced use-cases where the default implementation or its configurations are not sufficient. +Several new types have been added to support this: + +- `com.auth0.net.client.Auth0HttpClient` has been added to define the HTTP client interface. +- `com.auth0.net.client.DefaultHttpClient` is the default HTTP implementation that should be used in the majority of cases. It supports the same configurations as `HttpOptions`, but can be reused across API clients. It uses `OkHttp` as the networking client internally. +- `com.auth0.net.client.Auth0HttpRequest` is a lightweight representation of an HTTP request to execute. Internal API implementations will form the request. +- `com.auth0.net.client.Auth0HttpResponse` is a lightweight representation of an HTTP response. Internal API implementations will parse the response. +- `com.auth0.net.client.HttpMethod` is an `enum` representing the HTTP methods. + +### New deprecations + +- `com.auth0.client.HttpOptions` has been deprecated, in favor of configuring the `DefaultHttpClient` directly. +- `com.auth0.client.mgmt.ManagementAPI` constructors have been deprecated in favor of `ManagementAPI#newBuilder(String domain, String apiToken)`. +- `com.auth0.client.auth.AuthAPI` constructors have been deprecated in favor of `AuthAPI.newBuilder(String domain, String clientId)` and `AuthAPI.newBuilder(String domain, String clientId, String clientSecret)`. diff --git a/README.md b/README.md index 55e9fde34..1c1ce5b8a 100644 --- a/README.md +++ b/README.md @@ -1,776 +1,131 @@ -# Auth0 Java +> **Note** +> As part of our ongoing commitment to best security practices, we have rotated the signing keys used to sign previous releases of this SDK. As a result, new patch builds have been released using the new signing key. Please upgrade at your earliest convenience. +> +> While this change won't affect most developers, if you have implemented a dependency signature validation step in your build process, you may notice a warning that past releases can't be verified. This is expected, and a result of the key rotation process. Updating to the latest version will resolve this for you. -[![Build-Circle][circle-ci-badge]][circle-ci-url] -[![MIT][mit-badge]][mit-url] -[![Maven][maven-badge]][maven-url] -[![JCenter][jcenter-badge]][jcenter-url] -[![codecov][codecov-badge]][codecov-url] +![A Java client library for the Auth0 Authentication and Management APIs.](https://cdn.auth0.com/website/sdks/banners/auth0-java-banner.png) -Java client library for the [Auth0](https://auth0.com) platform. +![Build Status](https://img.shields.io/github/checks-status/auth0/auth0-java/master) +[![Coverage Status](https://codecov.io/gh/auth0/auth0-java/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/github/auth0/auth0-java) +[![License](http://img.shields.io/:license-mit-blue.svg?style=flat)](https://doge.mit-license.org/) +[![Maven Central](https://img.shields.io/maven-central/v/com.auth0/auth0.svg?style=flat-square)](https://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.auth0%22%20AND%20a%3A%22auth0%22) +[![javadoc](https://javadoc.io/badge2/com.auth0/auth0/javadoc.svg)](https://javadoc.io/doc/com.auth0/auth0) +[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/auth0/auth0-java) -## Download +:books: [Documentation](#documentation) - :rocket: [Getting Started](#getting-started) - :computer: [API Reference](#api-reference) :speech_balloon: [Feedback](#feedback) -Get Auth0 Java via Maven: +## Documentation +- [Examples](./EXAMPLES.md) - code samples for common auth0-java scenarios. +- [Migration Guide](./MIGRATION_GUIDE.md) - guidance for updating your application to use version 2 of auth0-java. +- [Docs site](https://www.auth0.com/docs) - explore our docs site and learn more about Auth0. + +## Getting Started + +### Requirements + +Java 8 or above. + +> `auth0-java` is intended for server-side JVM applications. Android applications should use the [Auth0.Android SDK](https://github.com/auth0/auth0.android). + +### Installation + +Add the dependency via Maven: ```xml com.auth0 auth0 - 1.42.0 + 2.27.0 ``` or Gradle: ```gradle -implementation 'com.auth0:auth0:1.42.0' +implementation 'com.auth0:auth0:2.27.0' ``` +### Configure the SDK -### Android - -The Auth0 Authentication API and User's Management API are available for Android in the `auth0.android` library. Check https://github.com/auth0/auth0.android for more information. +#### Authentication API Client -## Auth API +The Authentication API client is based on the [Auth0 Authentication API](https://auth0.com/docs/api/authentication). -The implementation is based on the [Authentication API Docs](https://auth0.com/docs/api/authentication). - -Create an `AuthAPI` instance by providing the Application details from the [dashboard](https://manage.auth0.com/#/applications). Read the [recommendations](#api-clients-recommendations) for keeping the resources usage low. +Create an `AuthAPI` instance by providing the Application details from the [dashboard](https://manage.auth0.com/#/applications). ```java -AuthAPI auth = new AuthAPI("{YOUR_DOMAIN}", "{YOUR_CLIENT_ID}", "{YOUR_CLIENT_SECRET}"); +AuthAPI auth = AuthAPI.newBuilder("{YOUR_DOMAIN}", "{YOUR_CLIENT_ID}", "{YOUR_CLIENT_SECRET}").build(); ``` -### Authorize - /authorize +#### Management API Client -Creates an `AuthorizeUrlBuilder` to authenticate the user with an OAuth provider. The `redirectUri` must be white-listed in the "Allowed Callback URLs" section of the Applications Settings. Parameters can be added to the final URL by using the builder methods. When ready, call `build()` and obtain the URL. +The Management API client is based on the [Management API Docs](https://auth0.com/docs/api/management/v2). -```AuthorizeUrlBuilder authorizeUrl(String redirectUri)``` +Create a `ManagementAPI` instance by providing the domain from the [Application dashboard](https://manage.auth0.com/#/applications) and a valid API Token. -Example: ```java -String url = auth.authorizeUrl("https://me.auth0.com/callback") - .withConnection("facebook") - .withAudience("https://api.me.auth0.com/users") - .withScope("openid contacts") - .withState("state123") - .build(); +ManagementAPI mgmt = ManagementAPI.newBuilder("{YOUR_DOMAIN}", "{YOUR_API_TOKEN}").build(); ``` -### Logout - /v2/logout -Creates a `LogoutUrlBuilder` to log out the user. The `returnToUrl` must be white-listed in the "Allowed Logout URLs" section of the Dashboard, depending on the value of `setClientId` this configuration should be set in the Application or in the Tenant Settings. Parameters can be added to the final URL by using the builder methods. When ready, call `build()` and obtain the URL. +OR -`LogoutUrlBuilder logoutUrl(String returnToUrl, boolean setClientId)` +Create a `ManagementAPI` instance by providing the domain from the [Application dashboard](https://manage.auth0.com/#/applications) and Token Provider. -Example: ```java -String url = auth.logoutUrl("https://me.auth0.com/home", true) - .useFederated(true) - .build(); +TokenProvider tokenProvider = SimpleTokenProvider.create("{YOUR_API_TOKEN}"); +ManagementAPI mgmt = ManagementAPI.newBuilder("{YOUR_DOMAIN}", TokenProvider).build(); ``` -### UserInfo - /userinfo -Creates a request to get the user information associated to a given access token. This will only work if the token has been granted the `openid` scope. - -`Request userInfo(String accessToken)` - -Example: -```java -Request request = auth.userInfo("nisd1h9dk.....s1doWJOsaf"); -try { - UserInfo info = request.execute(); - // info.getValues(); -} catch (APIException exception) { - // api error -} catch (Auth0Exception exception) { - // request error -} -``` - -### Reset Password - /dbconnections/change_password -Creates a request to reset the user's password. This will only work for db connections. - -`Request resetPassword(String email, String connection)` +The Management API is organized by entities represented by the Auth0 Management API objects. -Example: ```java -Request request = auth.resetPassword("user@domain.com", "Username-Password-Authentication"); -try { - request.execute(); -} catch (APIException exception) { - // api error -} catch (Auth0Exception exception) { - // request error -} -``` - - -### Sign Up - /dbconnections/signup -Creates a request to create a user. Up to 10 additional Sign Up fields can be added to the request. This will only work for db connections. - -`SignUpRequest signUp(String email, String username, String password, String connection)` - -`SignUpRequest signUp(String email, String password, String connection)` - -Example: -```java -Map fields = new HashMap<>(); -fields.put("age", "25"); -fields.put("city", "Buenos Aires"); -SignUpRequest request = auth.signUp("user@domain.com", "username", "password123", "Username-Password-Authentication") - .setCustomFields(fields); -try { - CreatedUser user = request.execute(); -} catch (APIException exception) { - // api error -} catch (Auth0Exception exception) { - // request error -} -``` - -### Exchange the Authorization Code - /oauth/token - -Creates a request to exchange the `code` previously obtained by calling the /authorize endpoint. The redirect URI must be the one sent in the /authorize call. - -`AuthRequest exchangeCode(String code, String redirectUri)` - -Example: -```java -AuthRequest request = auth.exchangeCode("asdfgh", "https://me.auth0.com/callback") - .setAudience("https://api.me.auth0.com/users") - .setScope("openid contacts"); -try { - TokenHolder holder = request.execute(); -} catch (APIException exception) { - // api error -} catch (Auth0Exception exception) { - // request error -} -``` - -### Log In with Password - /oauth/token - -Creates a request to log in the user with `username` and `password`. The connection used is the one defined as "Default Directory" in the account settings. - -`AuthRequest login(String emailOrUsername, String password)` - -Example: -```java -AuthRequest request = auth.login("me@domain.com", "password123") - .setAudience("https://api.me.auth0.com/users") - .setScope("openid contacts"); -try { - TokenHolder holder = request.execute(); -} catch (APIException exception) { - // api error -} catch (Auth0Exception exception) { - // request error -} -``` - -### Log In with Password Realm - /oauth/token - -Creates a request to log in the user with `username` and `password` using the Password Realm. - -`AuthRequest login(String emailOrUsername, String password, String realm)` - -Example: -```java -AuthRequest request = auth.login("me@domain.com", "password123", "Username-Password-Authentication") - .setAudience("https://api.me.auth0.com/users") - .setScope("openid contacts"); -try { - TokenHolder holder = request.execute(); -} catch (APIException exception) { - // api error -} catch (Auth0Exception exception) { - // request error -} -``` - -### Request Token for Audience - /oauth/token - -Creates a request to get a Token for the given Audience. - -`AuthRequest requestToken(String audience)` - -Example: -```java -AuthRequest request = auth.requestToken("https://api.me.auth0.com/users") - .setScope("openid contacts"); -try { - TokenHolder holder = request.execute(); -} catch (APIException exception) { - // api error -} catch (Auth0Exception exception) { - // request error -} -``` - -### Revoke Refresh Token - -Creates a request to revoke an existing Refresh Token. - -`Request revokeToken(String refreshToken)` - -Example: -```java -Request request = auth.revokeToken("nisd1h9dks1doWJOsaf"); -try { - request.execute(); -} catch (APIException exception) { - // api error -} catch (Auth0Exception exception) { - // request error -} -``` - -### Renew Authentication - -Creates a request to renew the authentication and get fresh new credentials using a valid Refresh Token. - -`AuthRequest renewAuth(String refreshToken)` - -Example: -```java -AuthRequest request = auth.renewAuth("nisd1h9dks1doWJOsaf"); -try { - TokenHolder holder = request.execute(); -} catch (APIException exception) { - // api error -} catch (Auth0Exception exception) { - // request error -} -``` - -### Passwordless Authentication - -This library supports [Passwordless Authentication](https://auth0.com/docs/connections/passwordless) to allow users to log in without the need to remember a password. - -The email flow supports sending both a code or link to initiate login: - -```java -try { - PasswordlessEmailResponse = auth.startPasswordlessEmailFlow("user@domain.com", PasswordlessEmailType.CODE) - .execute(); -} catch (Auth0Exception e) { - // handle request error -} -``` - -You can also initiate the passwordless flow by sending a code via SMS: - -```java -try { - PasswordlessSmsResponse result = auth.startPasswordlessSmsFlow("+16511234567") - .execute(); -} catch (Auth0Exception e) { - // handle request error -} -``` - -Using the verification code sent to the user, you can complete the passwordless authentication flow and obtain the tokens: - -```java -AuthRequest request = auth.exchangePasswordlessOtp("emailOrPhone", PasswordlessRealmType.EMAIL, new char[]{'c','o','d','e'}); -try { - TokenHolder tokens = request.execute(); -} catch (Auth0Exception e) { - // handle request error -} -``` - -### Organizations - -[Organizations](https://auth0.com/docs/organizations) is a set of features that provide better support for developers who build and maintain SaaS and Business-to-Business (B2B) applications. - -Note that Organizations is currently only available to customers on our Enterprise and Startup subscription plans. - -#### Log in to an organization - -Log in to an organization by using `withOrganization()` when building the Authorization URL: - -```java -AuthAPI auth = new AuthAPI("{YOUR_DOMAIN}", "{YOUR_CLIENT_ID}", "{YOUR_CLIENT_SECRET}"); -String url = auth.authorizeUrl("https://me.auth0.com/callback") - .withOrganization("{YOUR_ORGANIZATION_ID") - .build(); -``` - -**Important!** When logging into an organization, it is important to ensure the `org_id` claim of the ID Token matches the expected organization value. The `IdTokenVerifier` can be configured with an expected `org_id` claim value, as the example below demonstrates. -For more information, please read [Work with Tokens and Organizations](https://auth0.com/docs/organizations/using-tokens) on Auth0 Docs. -```java -IdTokenVerifier.init("{ISSUER}", "{AUDIENCE}", signatureVerifier) - .withOrganization("{ORG_ID}") - .build() - .verify(jwt); -``` - -### Accept user invitations - -Accept a user invitation by using `withInvitation()` when building the Authorization URL: - -``` -AuthAPI auth = new AuthAPI("{YOUR_DOMAIN}", "{YOUR_CLIENT_ID}", "{YOUR_CLIENT_SECRET}"); -String url = auth.authorizeUrl("https://me.auth0.com/callback") - .withOrganization("{YOUR_ORGANIZATION_ID") - .withInvitation("{YOUR_INVITATION_ID}") - .build(); -``` - -## Management API - -The implementation is based on the [Management API Docs](https://auth0.com/docs/api/management/v2). - -Create a `ManagementAPI` instance by providing the domain from the [Application dashboard](https://manage.auth0.com/#/applications) and a valid API Token. Read the [recommendations](#api-clients-recommendations) for keeping the resources usage low. - -```java -ManagementAPI mgmt = new ManagementAPI("{YOUR_DOMAIN}", "{YOUR_API_TOKEN}"); +User user = mgmt.users().get("auth0|user-id", new UserFilter()).execute().getBody(); +Role role = mgmt.roles().get("role-id").execute().getBody(); ``` You can use the Authentication API to obtain a token for a previously authorized Application: ```java -AuthAPI authAPI = new AuthAPI("{YOUR_DOMAIN}", "{YOUR_CLIENT_ID}", "{YOUR_CLIENT_SECRET}"); -AuthRequest authRequest = authAPI.requestToken("https://{YOUR_DOMAIN}/api/v2/"); -TokenHolder holder = authRequest.execute(); -ManagementAPI mgmt = new ManagementAPI("{YOUR_DOMAIN}", holder.getAccessToken()); +AuthAPI authAPI = AuthAPI.newBuilder("{YOUR_DOMAIN}", "{YOUR_CLIENT_ID}", "{YOUR_CLIENT_SECRET}").build(); +TokenRequest tokenRequest = authAPI.requestToken("https://{YOUR_DOMAIN}/api/v2/"); +TokenHolder holder = tokenRequest.execute().getBody(); +String accessToken = holder.getAccessToken(); +ManagementAPI mgmt = ManagementAPI.newBuilder("{YOUR_DOMAIN}", accessToken).build(); ``` -(Note that the snippet above should have error handling, and ideally cache the obtained token until it expires instead of requesting one access token for each Management API v2 invocation). - An expired token for an existing `ManagementAPI` instance can be replaced by calling the `setApiToken` method with the new token. -Click [here](https://auth0.com/docs/api/management/v2/tokens) for more information on how to obtain API Tokens. - - -The Management API is divided into different entities. Each of them have the list, create, update, delete and update methods plus a few more if corresponds. The calls are authenticated using the API Token given in the `ManagementAPI` instance creation and must contain the `scope` required by each entity. See the javadoc for details on which `scope` is expected for each call. - -* **Blacklists:** See [Docs](https://auth0.com/docs/api/management/v2#!/Blacklists/get_tokens). Access the methods by calling `mgmt.blacklists()`. -* **Client Grants:** See [Docs](https://auth0.com/docs/api/management/v2#!/Client_Grants/get_client_grants). Access the methods by calling `mgmt.clientGrants()`. This endpoint supports pagination. -* **Clients:** See [Docs](https://auth0.com/docs/api/management/v2#!/Clients/get_clients). Access the methods by calling `mgmt.clients()`. This endpoint supports pagination. -* **Connections:** See [Docs](https://auth0.com/docs/api/management/v2#!/Connections/get_connections). Access the methods by calling `mgmt.connections()`. This endpoint supports pagination. -* **Device Credentials:** See [Docs](https://auth0.com/docs/api/management/v2#!/Device_Credentials/get_device_credentials). Access the methods by calling `mgmt.deviceCredentials()`. -* **Email Providers:** See [Docs](https://auth0.com/docs/api/management/v2#!/Emails/get_provider). Access the methods by calling `mgmt.emailProvider()`. -* **Email Templates:** See [Docs](https://auth0.com/docs/api/management/v2#!/Email_Templates/get_email_templates_by_templateName). Access the methods by calling `mgmt.emailTemplates()`. -* **Grants:** See [Docs](https://auth0.com/docs/api/management/v2#!/Grants/get_grants). Access the methods by calling `mgmt.grants()`. This endpoint supports pagination. -* **Guardian:** See [Docs](https://auth0.com/docs/api/management/v2#!/Guardian/get_factors). Access the methods by calling `mgmt.guardian()`. -* **Jobs:** See [Docs](https://auth0.com/docs/api/management/v2#!/Jobs/get_jobs_by_id). Access the methods by calling `mgmt.jobs()`. -* **Logs:** See [Docs](https://auth0.com/docs/api/management/v2#!/Logs/get_logs). Access the methods by calling `mgmt.logEvents()`. This endpoint supports pagination. -* **Log Streams:** See [Docs](https://auth0.com/docs/api/management/v2#!/Log_Streams/get_log_streams). Access the methods by calling `mgmt.logStreams()`. -* **Resource Servers:** See [Docs](https://auth0.com/docs/api/management/v2#!/Resource_Servers/get_resource_servers). Access the methods by calling `mgmt.resourceServers()`. This endpoint supports pagination. -* **Roles:** See [Docs](https://auth0.com/docs/api/management/v2#!/Roles/get_roles). Access the methods by calling `mgmt.roles()`. This endpoint supports pagination. -* **Rules:** See [Docs](https://auth0.com/docs/api/management/v2#!/Rules/get_rules). Access the methods by calling `mgmt.rules()`. This endpoint supports pagination. -* **Stats:** See [Docs](https://auth0.com/docs/api/management/v2#!/Stats/get_active_users). Access the methods by calling `mgmt.stats()`. -* **Tenants:** See [Docs](https://auth0.com/docs/api/management/v2#!/Tenants/get_settings). Access the methods by calling `mgmt.tenants()`. -* **Tickets:** See [Docs](https://auth0.com/docs/api/management/v2#!/Tickets/post_email_verification). Access the methods by calling `mgmt.tickets()`. -* **User Blocks:** See [Docs](https://auth0.com/docs/api/management/v2#!/User_Blocks/get_user_blocks). Access the methods by calling `mgmt.userBlocks()`. -* **Users:** See [this](https://auth0.com/docs/api/management/v2#!/Users/get_users) and [this](https://auth0.com/docs/api/management/v2#!/Users_By_Email) doc. Access the methods by calling `mgmt.users()`. This endpoint supports pagination. - - -> Some of the endpoints above indicate they support paginated responses. You can request a page of items by passing in the filter instance the `page` and `per_page` parameters, and optionally `include_totals` to obtain a summary of the results. Refer to the "List Users" example below for details. - - -### Users - -#### List by Email - -Creates a request to list the Users by Email. This is the preferred and fastest way to query Users by Email, and should be used instead of calling the generic list method with an email query. An API Token with scope `read:users` is needed. If you want the identities.access_token property to be included, you will also need the scope `read:user_idp_tokens`. -You can pass an optional Filter to narrow the results in the response. - -`Request> listByEmail(String email, UserFilter filter)` - -Example: -```java -FieldsFilter filter = new FieldsFilter(); -//... -Request> request = mgmt.users().listByEmail("johndoe@auth0.com", filter); -try { - List response = request.execute(); -} catch (APIException exception) { - // api error -} catch (Auth0Exception exception) { - // request error -} -``` - -#### List - -Creates a request to list the Users. An API Token with scope `read:users` is needed. If you want the identities.access_token property to be included, you will also need the scope `read:user_idp_tokens`. -You can pass an optional Filter to narrow the results in the response. - -`Request list(UserFilter filter)` - -Example: -```java -UserFilter filter = new UserFilter() - .withPage(0, 20); -//... -Request request = mgmt.users().list(filter); -try { - UsersPage response = request.execute(); -} catch (APIException exception) { - // api error -} catch (Auth0Exception exception) { - // request error -} -``` - -#### Get - -Creates a request to get a User. An API Token with scope `read:users` is needed. If you want the identities.access_token property to be included, you will also need the scope `read:user_idp_tokens`. -You can pass an optional Filter to specify the fields you want to include or exclude from the response. - -`Request get(String userId, UserFilter filter)` - -Example: -```java -UserFilter filter = new UserFilter(); -//... -Request request = mgmt.users().get("auth0|123", filter); -try { - User response = request.execute(); -} catch (APIException exception) { - // api error -} catch (Auth0Exception exception) { - // request error -} -``` - -#### Create - -Creates a request to create a User. An API Token with scope `create:users` is needed. - -`Request create(User user)` - -Example: -```java -User data = new User("my-connection"); -//... -Request request = mgmt.users().create(data); -try { - User response = request.execute(); -} catch (APIException exception) { - // api error -} catch (Auth0Exception exception) { - // request error -} -``` - -#### Delete - -Creates a request to delete a User. An API Token with scope `delete:users` is needed. - -`Request delete(String userId)` - -Example: -```java -Request request = mgmt.users().delete("auth0|123"); -try { - request.execute(); -} catch (APIException exception) { - // api error -} catch (Auth0Exception exception) { - // request error -} -``` - -#### Update - -Creates a request to update a User. An API Token with scope `update:users` is needed. If you're updating app_metadata you'll also need `update:users_app_metadata` scope. - -`Request update(String userId, User user)` - -Example: -```java -User data = new User(); -//... -Request request = mgmt.users().update("auth0|123", data); -try { - User response = request.execute(); -} catch (APIException exception) { - // api error -} catch (Auth0Exception exception) { - // request error -} -``` - -#### Get Guardian Enrollments - -Creates a request to list the User's Guardian Enrollments. An API Token with scope `read:users` is needed. - -`Request> getEnrollments(String userId)` - -Example: -```java -Request> request = mgmt.users().getEnrollments("auth0|123"); -try { - List response = request.execute(); -} catch (APIException exception) { - // api error -} catch (Auth0Exception exception) { - // request error -} -``` - -#### Get Log Events - -Creates a request to list the User's Log Events. An API Token with scope `read:logs` is needed. -You can pass an optional Filter to narrow the results in the response. - -`Request getLogEvents(String userId, LogEventFilter filter)` - -Example: -```java -LogEventFilter filter = new LogEventFilter(); -//... -Request request = mgmt.users().getLogEvents("auth0|123", filter); -try { - LogEventsPage response = request.execute(); -} catch (APIException exception) { - // api error -} catch (Auth0Exception exception) { - // request error -} -``` - - -#### Delete Multifactor Provider - -Creates a request to delete the User's Multifactor Provider. An API Token with scope `update:users` is needed. - -`Request deleteMultifactorProvider(String userId, String provider)` - -Example: -```java -Request request = mgmt.users().deleteMultifactorProvider("auth0|123", "duo"); -try { - request.execute(); -} catch (APIException exception) { - // api error -} catch (Auth0Exception exception) { - // request error -} -``` - -#### Rotate Recovery Code - -Creates a request to rotate the User's Recovery Code. An API Token with scope `update:users` is needed. - -`Request rotateRecoveryCode(String userId)` - -Example: -```java -Request request = mgmt.users().rotateRecoveryCode("auth0|123"); -try { - RecoveryCode response = request.execute(); -} catch (APIException exception) { - // api error -} catch (Auth0Exception exception) { - // request error -} -``` - -#### Link Identities - -Creates a request to link two User identities. An API Token with scope `update:users` is needed. - -`Request> linkIdentity(String primaryUserId, String secondaryUserId, String provider, String connectionId)` - -Example: -```java -Request> request = mgmt.users().linkIdentity("auth0|123", "124", "facebook", "c90"); -try { - List response = request.execute(); -} catch (APIException exception) { - // api error -} catch (Auth0Exception exception) { - // request error -} -``` - -#### Un-Link Identities - -Creates a request to un-link two User identities. An API Token with scope `update:users` is needed. - -`Request> unlinkIdentity(String primaryUserId, String secondaryUserId, String provider)` - -Example: -```java -Request> request = mgmt.users().unlinkIdentity("auth0|123", "124", "facebook"); -try { - List response = request.execute(); -} catch (APIException exception) { - // api error -} catch (Auth0Exception exception) { - // request error -} -``` - -## Asynchronous requests - -Requests can be executed asynchronously, using the `executeAsync()` method, which returns a `CompletableFuture`. - -## API Clients Recommendations -The SDK implements a custom networking stack on top of the **OkHttp** library. The [official recommendation](https://square.github.io/okhttp/4.x/okhttp/okhttp3/-ok-http-client/#okhttpclients-should-be-shared) from Square is to re-use as much as possible these clients. However, it's not possible to pass an existing `OkHttpClient` instance to our `AuthAPI` and `ManagementAPI` clients. - -The networking client used by both the `AuthAPI` and `ManagementAPI` clients can be configured through the `HttpOptions`, which enables custom timeout configuration and proxy support: - -```java -HttpOptions options = new HttpOptions(); - -// configure timeouts; default is ten seconds for both connect and read timeouts: -options.setConnectTimeout(5); -options.setReadTimeout(15); - -// configure proxy: -Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("{IP-ADDRESS}", {PORT})); -ProxyOptions proxyOptions = new ProxyOptions(proxy); -options.setProxyOptions(proxyOptions); - -// create client -AuthAPI authAPI = new AuthAPI("{CLIENT_ID}", "{CLIENT_SECRET}", options); -``` - -Whenever you instantiate a client, a new `OkHttpClient` instance is created internally to handle the network requests. This instance is not directly exposed for customization. In order to reduce resource consumption, make use of the _singleton pattern_ to keep a single instance of this SDK's API client during the lifecycle of your application. - -For the particular case of the `ManagementAPI` client, if the token you've originally set has expired or you require to change its scopes, you can update the client's token with the `setApiToken(String)` method. - -## Error Handling - -The API Clients throw `Auth0Exception` when an unexpected error happens on a request execution, i.e. Connectivity or Timeout error. - -If you need to handle different error scenarios you need to catch first `APIException`, which provides methods to get a clue of what went wrong. - -The APIExplorer includes a list of response messages for each endpoint. You can get a clue of what went wrong by asking the Http status code: `exception.getStatusCode()`. i.e. a `status_code=403` would mean that the token has an insufficient scope. - -An error code will be included to categorize the type of error, you can get it by calling `exception.getError()`. If you want to see a user friendly description of what happened and why the request is failing check the `exception.getDescription()`. Finally, if the error response includes additional properties they can be obtained by calling `exception.getValue("{THE_KEY}")`. - - -``` -Example exception data -{ - statusCode: 400, - description: "Query validation error: 'String 'users' does not match pattern. Must be a comma separated list of the following values: name,strategy,options,enabled_clients,id,provisioning_ticket_url' on property fields (A comma separated list of fields to include or exclude (depending on include_fields) from the result, empty to retrieve all fields).", - error: "invalid_query_string" -} -``` - -## ID Token Validation - -This library also provides the ability to validate an OIDC-compliant ID Token, according to the [OIDC Specification](https://openid.net/specs/openid-connect-core-1_0-final.html#IDTokenValidation). - -### Verifying an ID Token signed with the RS256 signing algorithm - -To verify an ID Token that is signed using the RS256 signing algorithm, you will need to provide an implementation of -`PublicKeyProvider` that will return the public key used to verify the token's signature. The example below demonstrates how to use the `JwkProvider` from the [jwks-rsa-java](https://github.com/auth0/jwks-rsa-java) library: - -```java -JwkProvider provider = new JwkProviderBuilder("https://your-domain.auth0.com").build(); -SignatureVerifier sigVerifier = SignatureVerifier.forRS256(new PublicKeyProvider() { - @Override - public RSAPublicKey getPublicKeyById(String keyId) throws PublicKeyProviderException { - try { - return (RSAPublicKey) provider.get(keyId).getPublicKey(); - } catch (JwkException jwke) { - throw new PublicKeyProviderException("Error obtaining public key", jwke); - } - } -} - -IdTokenVerifier idTokenVerifier = IdTokenVerifier.init("https://your-domain.auth0.com/","your-client-id", signatureVerifier).build(); - -try { - idTokenVerifier.verify("token", "expected-nonce"); -} catch(IdTokenValidationException idtve) { - // Handle invalid token exception -} -``` - -### Verifying an ID Token signed with the HS256 signing algorithm - -To verify an ID Token that is signed using the HS256 signing algorithm: - -```java -SignatureVerifier signatureVerifier = SignatureVerifier.forHS256("your-client-secret"); -IdTokenVerifier idTokenVerifier = IdTokenVerifier.init("https://your-domain.auth0.com/","your-client-id", signatureVerifier).build(); - -try { - idTokenVerifier.verify("token", "expected-nonce"); -} catch(IdTokenValidationException idtve) { - // Handle invalid token exception -} -``` - -### Additional configuration options - -By default, time-based claims such as the token expiration (`exp` claim) will allow for a leeway of **60 seconds**. -You can customize the leeway by using the `withLeeway` when building the `IdTokenVerifier`: - -```java -IdTokenVerifier idTokenVerifier = IdTokenVerifier.init("https://your-domain.auth0.com/","your-client-id", signatureVerifier) - .withLeeway(120) // two minutes - .build(); -``` - -When verifying the token, the following methods are available to support different scenarios: - -```java -// Verify the token's signature and claims, excluding the nonce and auth_time claims -idTokenVerifier.verify("token"); - -// Verify the token's signature and claims, including the nonce. -// The expected nonce should be the nonce sent on the authorization request. -idTokenVerifier.verify("token", "expected-nonce"); - -// Verify the token's signature and claims, including the nonce and the auth_time claim. -// The maxAuthenticationAge parameter specifies the maximum amount of time since the end-user last actively authenticated, -// and it should match the max_age parameter sent on the authorization request. -idTokenVerifier.verify("token", "expected-nonce", 24 * 60 * 60); // maximum authentication age of 24 hours -``` - -## Documentation - -For more information about [Auth0](http://auth0.com) check our [documentation page](http://docs.auth0.com/). - -## What is Auth0? - -Auth0 helps you to: - -* Add authentication with [multiple authentication sources](https://docs.auth0.com/identityproviders), either social like **Google, Facebook, Microsoft Account, LinkedIn, GitHub, Twitter, Box, Salesforce, among others**, or enterprise identity systems like **Windows Azure AD, Google Apps, Active Directory, ADFS or any SAML Identity Provider**. -* Add authentication through more traditional **[username/password databases](https://docs.auth0.com/mysql-connection-tutorial)**. -* Add support for **[linking different user accounts](https://docs.auth0.com/link-accounts)** with the same user. -* Support for generating signed [Json Web Tokens](https://docs.auth0.com/jwt) to call your APIs and **flow the user identity** securely. -* Analytics of how, when and where users are logging in. -* Pull data from other sources and add it to the user profile, through [JavaScript rules](https://docs.auth0.com/rules). - -## Create a free Auth0 Account +See the [Auth0 Management API documentation](https://auth0.com/docs/api/management/v2/tokens) for more information on how to obtain API Tokens. -1. Go to [Auth0](https://auth0.com) and click Sign Up. -2. Use Google, GitHub or Microsoft Account to login. +## API Reference -## Issue Reporting +- [AuthAPI](https://javadoc.io/doc/com.auth0/auth0/latest/com/auth0/client/auth/AuthAPI.html) +- [ManagementAPI](https://javadoc.io/doc/com.auth0/auth0/latest/com/auth0/client/mgmt/ManagementAPI.html) -If you have found a bug or if you have a feature request, please report them at this repository issues section. Please do not report security vulnerabilities on the public GitHub issue tracker. The [Responsible Disclosure Program](https://auth0.com/whitehat) details the procedure for disclosing security issues. +## Feedback -## Author +### Contributing -[Auth0](https://auth0.com) +We appreciate feedback and contribution to this repo! Before you get started, please see the following: -## License +- [Auth0's general contribution guidelines](https://github.com/auth0/open-source-template/blob/master/GENERAL-CONTRIBUTING.md) +- [Auth0's code of conduct guidelines](https://github.com/auth0/open-source-template/blob/master/CODE-OF-CONDUCT.md) -This project is licensed under the MIT license. See the [LICENSE](LICENSE) file for more info. +### Raise an issue +To provide feedback or report a bug, [please raise an issue on our issue tracker](https://github.com/auth0/auth0-java/issues). +### Vulnerability Reporting +Please do not report security vulnerabilities on the public Github issue tracker. The [Responsible Disclosure Program](https://auth0.com/whitehat) details the procedure for disclosing security issues. - +--- -[circle-ci-badge]: https://img.shields.io/circleci/project/github/auth0/auth0-java.svg?style=flat -[circle-ci-url]: https://circleci.com/gh/auth0/auth0-java/tree/master -[mit-badge]: http://img.shields.io/:license-mit-blue.svg?style=flat -[mit-url]: https://raw.githubusercontent.com/auth0/auth0-java/master/LICENSE -[maven-badge]: https://img.shields.io/maven-central/v/com.auth0/auth0.svg -[maven-url]: http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.auth0%22%20AND%20a%3A%22auth0%22 -[jcenter-badge]: https://api.bintray.com/packages/auth0/java/auth0/images/download.svg -[jcenter-url]: https://bintray.com/auth0/java/auth0/_latestVersion -[codecov-badge]: https://codecov.io/gh/auth0/auth0-java/branch/master/graph/badge.svg -[codecov-url]: https://codecov.io/gh/auth0/auth0-java +

+ + + + Auth0 Logo + +

+

Auth0 is an easy to implement, adaptable authentication and authorization platform. To learn more checkout Why Auth0?

+

+This project is licensed under the MIT license. See the LICENSE file for more info.

\ No newline at end of file diff --git a/build.gradle b/build.gradle index f7e61fa6a..0cf814cb5 100644 --- a/build.gradle +++ b/build.gradle @@ -1,46 +1,33 @@ buildscript { - version = "1.42.0" + repositories { + jcenter() + } + + dependencies { + // https://github.com/melix/japicmp-gradle-plugin/issues/36 + classpath 'com.google.guava:guava:31.1-jre' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:2.1.0" + } } + plugins { id 'java' id 'jacoco' - id 'com.auth0.gradle.oss-library.java' + id 'me.champeau.gradle.japicmp' version '0.2.9' + id 'io.github.gradle-nexus.publish-plugin' version '2.0.0' } repositories { mavenCentral() } -def signingKey = findProperty('SIGNING_KEY') -def signingKeyPwd = findProperty('SIGNING_PASSWORD') - -signing { - useInMemoryPgpKeys(signingKey, signingKeyPwd) -} +apply from: rootProject.file('gradle/versioning.gradle') -group = 'com.auth0' +version = getVersionFromFile() +group = GROUP logger.lifecycle("Using version ${version} for ${name} group $group") -oss { - name 'auth0' - repository 'auth0-java' - organization 'auth0' - description 'Java client library for the Auth0 platform.' - baselineCompareVersion '1.27.0' - - developers { - auth0 { - displayName = 'Auth0' - email = 'oss@auth0.com' - } - lbalmaceda { - displayName = 'Luciano Balmaceda' - email = 'luciano.balmaceda@auth0.com' - } - } -} - jacocoTestReport { reports { xml.enabled = true @@ -65,29 +52,109 @@ compileTestJava { options.compilerArgs << "-Xlint:deprecation" << "-Werror" } +import me.champeau.gradle.japicmp.JapicmpTask + +project.afterEvaluate { + + def versions = project.ext.testInJavaVersions + for (pluginJavaTestVersion in versions) { + def taskName = "testInJava-${pluginJavaTestVersion}" + tasks.register(taskName, Test) { + def versionToUse = taskName.split("-").getAt(1) as Integer + description = "Runs unit tests on Java version ${versionToUse}." + project.logger.quiet("Test will be running in ${versionToUse}") + group = 'verification' + javaLauncher.set(javaToolchains.launcherFor { + languageVersion = JavaLanguageVersion.of(versionToUse) + }) + shouldRunAfter(tasks.named('test')) + } + tasks.named('check') { + dependsOn(taskName) + } + } + + project.configure(project) { + def baselineVersion = project.ext.baselineCompareVersion + task('apiDiff', type: JapicmpTask, dependsOn: 'jar') { + oldClasspath = files(getBaselineJar(project, baselineVersion)) + newClasspath = files(jar.archiveFile) + onlyModified = true + failOnModification = true + ignoreMissingClasses = true + htmlOutputFile = file("$buildDir/reports/apiDiff/apiDiff.html") + txtOutputFile = file("$buildDir/reports/apiDiff/apiDiff.txt") + doLast { + project.logger.quiet("Comparing against baseline version ${baselineVersion}") + } + } + } +} + +private static File getBaselineJar(Project project, String baselineVersion) { + // Use detached configuration: https://github.com/square/okhttp/blob/master/build.gradle#L270 + def group = project.group + try { + def baseline = "${project.group}:${project.name}:$baselineVersion" + project.group = 'virtual_group_for_japicmp' + def dependency = project.dependencies.create(baseline + "@jar") + return project.configurations.detachedConfiguration(dependency).files.find { + it.name == "${project.name}-${baselineVersion}.jar" + } + } finally { + project.group = group + } +} + + test { testLogging { events "skipped", "failed" exceptionFormat "short" } + useJUnitPlatform() } ext { - okhttpVersion = '4.10.0' + okhttpVersion = '4.12.0' hamcrestVersion = '2.2' + jupiterVersion = '5.9.3' + + baselineCompareVersion = '2.0.0' + testInJavaVersions = [8, 11, 17, 21] } dependencies { - implementation "com.squareup.okhttp3:okhttp:${okhttpVersion}" + // TODO remove direct dependency when OkHttp 4.12.0 is released + implementation ("com.squareup.okhttp3:okhttp:${okhttpVersion}") { + exclude group: 'com.squareup.okhttp3', module: 'okio' + exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib' + exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-jdk8' + } + implementation "com.squareup.okio:okio:3.5.0" + + implementation "org.jetbrains.kotlin:kotlin-stdlib:2.1.0" + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:2.1.0" + implementation "com.squareup.okhttp3:logging-interceptor:${okhttpVersion}" - implementation "com.fasterxml.jackson.core:jackson-databind:2.13.2.2" - implementation "com.auth0:java-jwt:3.19.1" - implementation "net.jodah:failsafe:2.4.1" + implementation "com.fasterxml.jackson.core:jackson-databind:2.15.0" + implementation "com.auth0:java-jwt:4.4.0" + implementation "net.jodah:failsafe:2.4.4" - testImplementation "org.bouncycastle:bcprov-jdk15on:1.68" - testImplementation "org.mockito:mockito-core:3.7.7" + testImplementation "org.mockito:mockito-core:4.8.1" testImplementation "com.squareup.okhttp3:mockwebserver:${okhttpVersion}" - testImplementation "org.hamcrest:hamcrest-core:${hamcrestVersion}" - testImplementation "org.hamcrest:hamcrest-library:${hamcrestVersion}" - testImplementation "junit:junit:4.13.1" + testImplementation "org.hamcrest:hamcrest:${hamcrestVersion}" + testImplementation "org.junit.jupiter:junit-jupiter-api:${jupiterVersion}" + testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${jupiterVersion}" + + // Override MockWebServer's junit transitive dependency to latest v4 + constraints { + testImplementation( group: 'junit', name: 'junit'){ + version{ + strictly "[4.13.2]" + } + } + } } + +apply from: rootProject.file('gradle/maven-publish.gradle') diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 000000000..69714a96a --- /dev/null +++ b/gradle.properties @@ -0,0 +1,21 @@ +GROUP=com.auth0 +POM_ARTIFACT_ID=auth0 +VERSION_NAME=2.12.0 + +POM_NAME=auth0-java +POM_DESCRIPTION=Java client library for the Auth0 platform +POM_PACKAGING=jar + +POM_URL=https://github.com/auth0/auth0-java +POM_SCM_URL=https://github.com/auth0/auth0-java + +POM_SCM_CONNECTION=scm:git:https://github.com/auth0/auth0-java.git +POM_SCM_DEV_CONNECTION=scm:git:https://github.com/auth0/auth0-java.git + +POM_LICENCE_NAME=The MIT License (MIT) +POM_LICENCE_URL=https://raw.githubusercontent.com/auth0/auth0-java/master/LICENSE +POM_LICENCE_DIST=repo + +POM_DEVELOPER_ID=auth0 +POM_DEVELOPER_NAME=Auth0 +POM_DEVELOPER_EMAIL=oss@auth0.com diff --git a/gradle/maven-publish.gradle b/gradle/maven-publish.gradle new file mode 100644 index 000000000..e458d769b --- /dev/null +++ b/gradle/maven-publish.gradle @@ -0,0 +1,101 @@ +apply plugin: 'maven-publish' +apply plugin: 'signing' + +task('sourcesJar', type: Jar, dependsOn: classes) { + archiveClassifier = 'sources' + from sourceSets.main.allSource +} + +task('javadocJar', type: Jar, dependsOn: javadoc) { + archiveClassifier = 'javadoc' + from javadoc.getDestinationDir() +} +tasks.withType(Javadoc).configureEach { + javadocTool = javaToolchains.javadocToolFor { + // Use latest JDK for javadoc generation + languageVersion = JavaLanguageVersion.of(17) + } +} + +javadoc { + // Specify the Java version that the project will use + options.addStringOption('-release', "8") +} +artifacts { + archives sourcesJar, javadocJar +} + +publishing { + publications { + mavenJava(MavenPublication) { + from components.java + + artifact sourcesJar + artifact javadocJar + + groupId = GROUP + artifactId = POM_ARTIFACT_ID + version = getVersionName() + + pom { + name = POM_NAME + packaging = POM_PACKAGING + description = POM_DESCRIPTION + url = POM_URL + + licenses { + license { + name = POM_LICENCE_NAME + url = POM_LICENCE_URL + distribution = POM_LICENCE_DIST + } + } + + developers { + developer { + id = POM_DEVELOPER_ID + name = POM_DEVELOPER_NAME + email = POM_DEVELOPER_EMAIL + } + } + + scm { + url = POM_SCM_URL + connection = POM_SCM_CONNECTION + developerConnection = POM_SCM_DEV_CONNECTION + } + } + } + } +} + +nexusPublishing { + repositories { + sonatype { + nexusUrl.set(uri('https://ossrh-staging-api.central.sonatype.com/service/local/')) + snapshotRepositoryUrl.set(uri('https://central.sonatype.com/repository/maven-snapshots/')) + username.set(System.getenv("MAVEN_USERNAME")) + password.set(System.getenv("MAVEN_PASSWORD")) + } + } +} + +signing { + def signingKey = System.getenv("SIGNING_KEY") + def signingPassword = System.getenv("SIGNING_PASSWORD") + useInMemoryPgpKeys(signingKey, signingPassword) + + sign publishing.publications.mavenJava +} + +javadoc { + if(JavaVersion.current().isJava9Compatible()) { + options.addBooleanOption('html5', true) + } +} + +tasks.named('publish').configure { + dependsOn tasks.named('assemble') +} + + diff --git a/gradle/versioning.gradle b/gradle/versioning.gradle new file mode 100644 index 000000000..9a8dae58d --- /dev/null +++ b/gradle/versioning.gradle @@ -0,0 +1,17 @@ +def getVersionFromFile() { + def versionFile = rootProject.file('.version') + return versionFile.text.readLines().first().trim() +} + +def isSnapshot() { + return hasProperty('isSnapshot') ? isSnapshot.toBoolean() : true +} + +def getVersionName() { + return isSnapshot() ? project.version+"-SNAPSHOT" : project.version +} + +ext { + getVersionName = this.&getVersionName + getVersionFromFile = this.&getVersionFromFile +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index e708b1c02..249e5832f 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1c4bcc29e..8049c684f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 4f906e0c8..a69d9cb6c 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ -#!/usr/bin/env sh +#!/bin/sh # -# Copyright 2015 the original author or authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,67 +17,101 @@ # ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +APP_BASE_NAME=${0##*/} # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar @@ -87,9 +121,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -98,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -106,80 +140,101 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=`expr $i + 1` + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index 107acd32c..53a6b238d 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,89 +1,91 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/opslevel.yml b/opslevel.yml new file mode 100644 index 000000000..009a5ec0b --- /dev/null +++ b/opslevel.yml @@ -0,0 +1,6 @@ +--- +version: 1 +repository: + owner: dx_sdks + tier: + tags: diff --git a/settings.gradle b/settings.gradle index d798faa94..a32c80c43 100644 --- a/settings.gradle +++ b/settings.gradle @@ -2,9 +2,6 @@ pluginManagement { repositories { gradlePluginPortal() } - plugins { - id 'com.auth0.gradle.oss-library.java' version '0.17.2' - } } rootProject.name = 'auth0' diff --git a/src/main/java/com/auth0/client/HttpOptions.java b/src/main/java/com/auth0/client/HttpOptions.java index 7ae3134f8..186f5ee14 100644 --- a/src/main/java/com/auth0/client/HttpOptions.java +++ b/src/main/java/com/auth0/client/HttpOptions.java @@ -2,7 +2,9 @@ /** * Used to configure additional configuration options when customizing the API client instance. + * @deprecated use the {@link com.auth0.net.client.DefaultHttpClient} to configure HTTP client behavior */ +@Deprecated public class HttpOptions { private ProxyOptions proxyOptions; diff --git a/src/main/java/com/auth0/client/auth/AuthAPI.java b/src/main/java/com/auth0/client/auth/AuthAPI.java index 798fb002d..6486727ee 100644 --- a/src/main/java/com/auth0/client/auth/AuthAPI.java +++ b/src/main/java/com/auth0/client/auth/AuthAPI.java @@ -1,29 +1,47 @@ package com.auth0.client.auth; -import com.auth0.client.HttpOptions; -import com.auth0.client.LoggingOptions; -import com.auth0.client.ProxyOptions; -import com.auth0.json.auth.PasswordlessEmailResponse; -import com.auth0.json.auth.PasswordlessSmsResponse; -import com.auth0.json.auth.UserInfo; -import com.auth0.net.Request; +import com.auth0.client.mgmt.ManagementAPI; +import com.auth0.json.ObjectMapperProvider; +import com.auth0.json.auth.*; import com.auth0.net.*; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.DefaultHttpClient; +import com.auth0.net.client.HttpMethod; import com.auth0.utils.Asserts; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; -import okhttp3.*; -import okhttp3.logging.HttpLoggingInterceptor; -import okhttp3.logging.HttpLoggingInterceptor.Level; +import okhttp3.HttpUrl; +import okhttp3.OkHttpClient; +import org.jetbrains.annotations.TestOnly; -import java.io.IOException; -import java.util.concurrent.TimeUnit; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import static com.auth0.json.ObjectMapperProvider.getMapper; /** - * Class that provides an implementation of some of the Authentication and Authorization API methods defined in https://auth0.com/docs/api/authentication. - * To begin create a new instance of {@link #AuthAPI(String, String, String)} using the tenant domain, and the Application's client id and client secret. + * Class that provides an implementation of of the Authentication and Authorization API methods defined by the + * Auth0 Authentication API. + * Instances are created using the {@link Builder}. If you are also using the {@link ManagementAPI}, it is recommended + * to configure each with the same {@link DefaultHttpClient} to enable both API clients to share the same Http client. + *

+ * To use with a confidential client, instantiate an instance with a client secret: + *

+ * {@code
+ * AuthAPI auth = AuthAPI.newBuilder("{DOMAIN}", "{CLIENT-ID}", "{CLIENT-SECRET}").build();
+ * }
+ * 
*

- * This class is not entirely thread-safe: - * A new immutable {@link OkHttpClient} instance is being created with each instantiation, not sharing the thread pool - * with any prior existing client instance. + * To use with a public client, or when only using APIs that do not require a client secret: + *

+ * {@code
+ * AuthAPI auth = AuthAPI.newBuilder("{DOMAIN}", "{CLIENT-ID}").build();
+ * }
+ * 
+ * Operations that always require a client secret will throw a {@code InvalidStateException} if the client is not created + * with a secret. */ @SuppressWarnings("WeakerAccess") public class AuthAPI { @@ -41,25 +59,29 @@ public class AuthAPI { private static final String KEY_OTP = "otp"; private static final String KEY_REALM = "realm"; private static final String KEY_MFA_TOKEN = "mfa_token"; - + private static final String KEY_CLIENT_ASSERTION = "client_assertion"; + private static final String KEY_CLIENT_ASSERTION_TYPE = "client_assertion_type"; private static final String PATH_OAUTH = "oauth"; private static final String PATH_TOKEN = "token"; private static final String PATH_DBCONNECTIONS = "dbconnections"; private static final String PATH_REVOKE = "revoke"; private static final String PATH_PASSWORDLESS = "passwordless"; private static final String PATH_START = "start"; + private static final String KEY_ORGANIZATION = "organization"; + private static final String KEY_PHONE_NUMBER = "phone_number"; - private final OkHttpClient client; + private final Auth0HttpClient client; private final String clientId; private final String clientSecret; + private final ClientAssertionSigner clientAssertionSigner; private final HttpUrl baseUrl; - private final TelemetryInterceptor telemetry; - private final HttpLoggingInterceptor logging; /** * Create a new instance with the given tenant's domain, application's client id and client secret. - * These values can be obtained at https://manage.auth0.com/#/applications/{YOUR_CLIENT_ID}/settings. - * In addition, accepts an {@link HttpOptions} that will be used to configure the networking client. + * These values can be obtained at {@code https://manage.auth0.com/#/applications/{YOUR_CLIENT_ID}/settings}. + * In addition, accepts an {@link com.auth0.client.HttpOptions} that will be used to configure the networking client. + * + * @deprecated Use the {@link Builder} to configure and create instances. * * @param domain tenant's domain. * @param clientId the application's client id. @@ -67,140 +89,106 @@ public class AuthAPI { * @param options configuration options for this client instance. * @see #AuthAPI(String, String, String) */ - public AuthAPI(String domain, String clientId, String clientSecret, HttpOptions options) { - Asserts.assertNotNull(domain, "domain"); - Asserts.assertNotNull(clientId, "client id"); - Asserts.assertNotNull(clientSecret, "client secret"); - Asserts.assertNotNull(options, "client options"); - - this.baseUrl = createBaseUrl(domain); - if (baseUrl == null) { - throw new IllegalArgumentException("The domain had an invalid format and couldn't be parsed as an URL."); - } - this.clientId = clientId; - this.clientSecret = clientSecret; - - telemetry = new TelemetryInterceptor(); - logging = new HttpLoggingInterceptor(); - client = buildNetworkingClient(options); + @Deprecated + @SuppressWarnings("deprecation") + public AuthAPI(String domain, String clientId, String clientSecret, com.auth0.client.HttpOptions options) { + this(domain, clientId, clientSecret, null, buildNetworkingClient(options)); } /** * Create a new instance with the given tenant's domain, application's client id and client secret. - * These values can be obtained at https://manage.auth0.com/#/applications/{YOUR_CLIENT_ID}/settings. + * These values can be obtained at {@code https://manage.auth0.com/#/applications/{YOUR_CLIENT_ID}/}settings. + * + * @deprecated Use the {@link Builder} to configure and create instances. * * @param domain tenant's domain. * @param clientId the application's client id. * @param clientSecret the application's client secret. */ + @Deprecated public AuthAPI(String domain, String clientId, String clientSecret) { - this(domain, clientId, clientSecret, new HttpOptions()); + this(domain, clientId, clientSecret, new com.auth0.client.HttpOptions()); } /** - * Given a set of options, it creates a new instance of the {@link OkHttpClient} - * configuring them according to their availability. - * - * @param options the options to set to the client. - * @return a new networking client instance configured as requested. + * Initialize a new {@link Builder} to configure and create an instance. Use this to construct an instance + * with a client secret when using a confidential client (Regular Web Application). + * @param domain the tenant's domain. Must be a non-null valid HTTPS URL. + * @param clientId the application's client ID. + * @param clientSecret the applications client secret. + * @return a Builder for further configuration. */ - private OkHttpClient buildNetworkingClient(HttpOptions options) { - OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder(); - final ProxyOptions proxyOptions = options.getProxyOptions(); - if (proxyOptions != null) { - //Set proxy - clientBuilder.proxy(proxyOptions.getProxy()); - //Set authentication, if present - final String proxyAuth = proxyOptions.getBasicAuthentication(); - if (proxyAuth != null) { - clientBuilder.proxyAuthenticator(new Authenticator() { - - private static final String PROXY_AUTHORIZATION_HEADER = "Proxy-Authorization"; - - @Override - public okhttp3.Request authenticate(Route route, Response response) throws IOException { - if (response.request().header(PROXY_AUTHORIZATION_HEADER) != null) { - return null; - } - return response.request().newBuilder() - .header(PROXY_AUTHORIZATION_HEADER, proxyAuth) - .build(); - } - }); - } - } - configureLogging(options.getLoggingOptions()); - Dispatcher dispatcher = new Dispatcher(); - dispatcher.setMaxRequests(options.getMaxRequests()); - dispatcher.setMaxRequestsPerHost(options.getMaxRequestsPerHost()); - return clientBuilder - .addInterceptor(logging) - .addInterceptor(telemetry) - .connectTimeout(options.getConnectTimeout(), TimeUnit.SECONDS) - .readTimeout(options.getReadTimeout(), TimeUnit.SECONDS) - .dispatcher(dispatcher) - .build(); + public static AuthAPI.Builder newBuilder(String domain, String clientId, String clientSecret) { + return new AuthAPI.Builder(domain, clientId).withClientSecret(clientSecret); } /** - * Avoid sending Telemetry data in every request to the Auth0 servers. + * Initialize a new {@link Builder} to configure and create an instance. Use this to construct an instance + * with a client assertion signer used in place of a client secret when calling token APIs. + * + * @param domain the tenant's domain. Must be a non-null valid HTTPS URL. + * @param clientId the application's client ID. + * @param clientAssertionSigner the {@code ClientAssertionSigner} used to create the signed client assertion. + * @return a Builder for further configuration. */ - public void doNotSendTelemetry() { - telemetry.setEnabled(false); + public static AuthAPI.Builder newBuilder(String domain, String clientId, ClientAssertionSigner clientAssertionSigner) { + return new AuthAPI.Builder(domain, clientId).withClientAssertionSigner(clientAssertionSigner); } /** - * Setter for the Telemetry to send in every request to Auth0. - * - * @param telemetry to send in every request to Auth0 + * Initialize a new {@link Builder} to configure and create an instance. Use this to construct an instance + * without a client secret (for example, when only using APIs that do not require a secret). + * @param domain the tenant's domain. Must be a non-null valid HTTPS URL. + * @param clientId the application's client ID. + * @return a Builder for further configuration. */ - public void setTelemetry(Telemetry telemetry) { - this.telemetry.setTelemetry(telemetry); + public static AuthAPI.Builder newBuilder(String domain, String clientId) { + return new AuthAPI.Builder(domain, clientId); } + private AuthAPI(String domain, String clientId, String clientSecret, ClientAssertionSigner clientAssertionSigner, Auth0HttpClient httpClient) { + Asserts.assertNotNull(domain, "domain"); + Asserts.assertNotNull(clientId, "client id"); + Asserts.assertNotNull(httpClient, "Http client"); + + this.baseUrl = createBaseUrl(domain); + if (baseUrl == null) { + throw new IllegalArgumentException("The domain had an invalid format and couldn't be parsed as an URL."); + } + this.clientId = clientId; + this.clientSecret = clientSecret; + this.clientAssertionSigner = clientAssertionSigner; + this.client = httpClient; + } + + /** - * @deprecated use the logging configuration available in {@link HttpOptions#setLoggingOptions(LoggingOptions)} - * - * Whether to enable or not the current HTTP Logger for every request and response line, body, and headers. - * Warning: Enabling logging can leek sensitive information, and should only be done in a controlled, non-production environment. + * Given a set of options, it creates a new instance of the {@link OkHttpClient} + * configuring them according to their availability. * - * @param enabled whether to enable the HTTP logger or not. + * @param options the options to set to the client. + * @return a new networking client instance configured as requested. */ - @Deprecated - public void setLoggingEnabled(boolean enabled) { - logging.setLevel(enabled ? Level.BODY : Level.NONE); + @SuppressWarnings("deprecation") + private static Auth0HttpClient buildNetworkingClient(com.auth0.client.HttpOptions options) { + Asserts.assertNotNull(options, "Http options"); + return DefaultHttpClient.newBuilder() + .withLogging(options.getLoggingOptions()) + .withMaxRetries(options.getManagementAPIMaxRetries()) + .withMaxRequests(options.getMaxRequests()) + .withMaxRequestsPerHost(options.getMaxRequestsPerHost()) + .withProxy(options.getProxyOptions()) + .withConnectTimeout(options.getConnectTimeout()) + .withReadTimeout(options.getReadTimeout()) + .build(); } - private void configureLogging(LoggingOptions loggingOptions) { - if (loggingOptions == null) { - logging.setLevel(Level.NONE); - return; - } - switch (loggingOptions.getLogLevel()) { - case BASIC: - logging.setLevel(Level.BASIC); - break; - case HEADERS: - logging.setLevel(Level.HEADERS); - break; - case BODY: - logging.setLevel(Level.BODY); - break; - case NONE: - default: - logging.setLevel(Level.NONE); - } - for (String header : loggingOptions.getHeadersToRedact()) { - logging.redactHeader(header); - } + @TestOnly + Auth0HttpClient getHttpClient() { + return this.client; } - //Visible for Testing - OkHttpClient getClient() { - return client; - } - - //Visible for Testing + @TestOnly HttpUrl getBaseUrl() { return baseUrl; } @@ -218,8 +206,7 @@ private HttpUrl createBaseUrl(String domain) { * i.e.: *
      * {@code
-     * AuthAPI auth = new AuthAPI("me.auth0.com", "B3c6RYhk1v9SbIJcRIOwu62gIUGsnze", "2679NfkaBn62e6w5E8zNEzjr-yWfkaBne");
-     * String url = auth.authorizeUrl("https://me.auth0.com/callback")
+     * String url = authAPI.authorizeUrl("https://me.auth0.com/callback")
      *      .withConnection("facebook")
      *      .withAudience("https://api.me.auth0.com/users")
      *      .withScope("openid contacts")
@@ -238,13 +225,213 @@ public AuthorizeUrlBuilder authorizeUrl(String redirectUri) {
         return AuthorizeUrlBuilder.newInstance(baseUrl, clientId, redirectUri);
     }
 
+    public Request authorizeBackChannel(String scope, String bindingMessage, Map loginHint) {
+        return authorizeBackChannel(scope, bindingMessage, loginHint, null, null);
+    }
+
+    public Request authorizeBackChannel(String scope, String bindingMessage, Map loginHint, String audience, Integer requestExpiry) {
+        Asserts.assertNotNull(scope, "scope");
+        Asserts.assertNotNull(bindingMessage, "binding message");
+        Asserts.assertNotNull(loginHint, "login hint");
+
+        String url = baseUrl
+            .newBuilder()
+            .addPathSegment("bc-authorize")
+            .build()
+            .toString();
+
+        FormBodyRequest request = new FormBodyRequest<>(client, null, url, HttpMethod.POST, new TypeReference() {});
+
+        request.addParameter(KEY_CLIENT_ID, clientId);
+        addClientAuthentication(request, false);
+        request.addParameter("scope", scope);
+        request.addParameter("binding_message", bindingMessage);
+
+        if(Objects.nonNull(audience)){
+            request.addParameter(KEY_AUDIENCE, audience);
+        }
+        if(Objects.nonNull(requestExpiry)){
+            request.addParameter("requested_expiry", requestExpiry);
+        }
+
+        try {
+            String loginHintJson = getMapper().writeValueAsString(loginHint);
+            request.addParameter("login_hint", loginHintJson);
+        }
+        catch (JsonProcessingException e) {
+            throw new IllegalArgumentException("'loginHint' must be a map that can be serialized to JSON", e);
+        }
+        return request;
+    }
+
+    public Request getBackChannelLoginStatus(String authReqId, String grantType) {
+        Asserts.assertNotNull(authReqId, "auth req id");
+        Asserts.assertNotNull(grantType, "grant type");
+
+        String url = getTokenUrl();
+
+        FormBodyRequest request = new FormBodyRequest<>(client, null, url, HttpMethod.POST, new TypeReference() {});
+
+        request.addParameter(KEY_CLIENT_ID, clientId);
+        addClientAuthentication(request, false);
+        request.addParameter("auth_req_id", authReqId);
+        request.addParameter(KEY_GRANT_TYPE, grantType);
+
+        return request;
+    }
+
+    /**
+     * Builds an authorization URL for Pushed Authorization Requests (PAR)
+     * @param requestUri the {@code request_uri} parameter from a successful pushed authorization request.
+     * @see AuthAPI#pushedAuthorizationRequest(String, String, Map)
+     * @see RFC 9126
+     * @return the {@code request_uri} from a successful pushed authorization request.
+     */
+    public String authorizeUrlWithPAR(String requestUri) {
+        Asserts.assertNotNull(requestUri, "request uri");
+        return baseUrl
+            .newBuilder()
+            .addPathSegment("authorize")
+            .addQueryParameter("client_id", clientId)
+            .addQueryParameter("request_uri", requestUri)
+            .build()
+            .toString();
+    }
+
+    /**
+     * Builds an authorization URL for JWT-Secured Authorization Request (JAR)
+     * @param request the {@code request} parameter value. As specified, it must be a signed JWT and contain claims representing the authorization parameters.
+     * @see AuthAPI#pushedAuthorizationRequestWithJAR(String)
+     * @see Authorization Code Flow with JWT-Secured Authorization Requests (JAR)
+     * @see RFC 9101
+     * @return the authorization URL to redirect users to for authentication.
+     */
+    public String authorizeUrlWithJAR(String request) {
+        Asserts.assertNotNull(request, "request");
+        return baseUrl
+            .newBuilder()
+            .addPathSegment("authorize")
+            .addQueryParameter("client_id", clientId)
+            .addQueryParameter("request", request)
+            .build()
+            .toString();
+    }
+
+    /**
+     * Builds a request to make a Pushed Authorization Request (PAR) to receive a {@code request_uri} to send to the {@code /authorize} endpoint.
+     * @param redirectUri the URL to redirect to after authorization has been granted by the user. Your Auth0 application
+     *                    must have this URL as one of its Allowed Callback URLs. Must be a valid non-encoded URL.
+     * @param responseType the response type to set. Must not be null.
+     * @param params an optional map of key/value pairs representing any additional parameters to send on the request.
+     * @see RFC 9126
+     * @return a request to execute.
+     */
+    public Request pushedAuthorizationRequest(String redirectUri, String responseType, Map params) {
+        return pushedAuthorizationRequest(redirectUri, responseType, params, null);
+    }
+
+    /**
+     * Builds a request to make a Pushed Authorization Request (PAR) to receive a {@code request_uri} to send to the {@code /authorize} endpoint.
+     * @param redirectUri the URL to redirect to after authorization has been granted by the user. Your Auth0 application
+     *                    must have this URL as one of its Allowed Callback URLs. Must be a valid non-encoded URL.
+     * @param responseType the response type to set. Must not be null.
+     * @param params an optional map of key/value pairs representing any additional parameters to send on the request.
+     * @param authorizationDetails A list of maps representing the value of the (optional) {@code authorization_details} parameter, used to perform Rich Authorization Requests. The list will be serialized to JSON and sent on the request.
+     * @see #pushedAuthorizationRequest(String, String, Map, List)
+     * @see RFC 9126
+     * @see RFC 9396
+     * @see Authorization Code Flow with Rich Authorization Requests (RAR)
+     * @return a request to execute.
+     */
+    public Request pushedAuthorizationRequest(String redirectUri, String responseType, Map params, List> authorizationDetails) {
+        Asserts.assertValidUrl(redirectUri, "redirect uri");
+        Asserts.assertNotNull(responseType, "response type");
+
+        String url = baseUrl
+            .newBuilder()
+            .addPathSegments("oauth/par")
+            .build()
+            .toString();
+
+        FormBodyRequest request = new FormBodyRequest<>(client, null, url, HttpMethod.POST, new TypeReference() {});
+        request.addParameter("client_id", clientId);
+        request.addParameter("redirect_uri", redirectUri);
+        request.addParameter("response_type", responseType);
+        if (Objects.nonNull(this.clientSecret)) {
+            request.addParameter("client_secret", clientSecret);
+        }
+        if (params != null) {
+            params.forEach(request::addParameter);
+        }
+        try {
+            if (Objects.nonNull(authorizationDetails)) {
+                String authDetailsJson = getMapper().writeValueAsString(authorizationDetails);
+                request.addParameter("authorization_details", authDetailsJson);
+            }
+        } catch (JsonProcessingException e) {
+            throw new IllegalArgumentException("'authorizationDetails' must be a list that can be serialized to JSON", e);
+        }
+        return request;
+    }
+
+    /**
+     * Builds a request to make a Pushed Authorization Request (PAR) with JWT-Secured Authorization Requests (JAR), to receive a {@code request_uri} to send to the {@code /authorize} endpoint.
+     * @param request The signed JWT containing the authorization parameters as claims.
+     * @see #pushedAuthorizationRequestWithJAR(String, List)
+     * @see Authorization Code Flow with PAR and JAR
+     * @see RFC 9101
+     * @see RFC 9126
+     * @return a request to execute.
+     */
+    public Request pushedAuthorizationRequestWithJAR(String request) {
+        return pushedAuthorizationRequestWithJAR(request, null);
+    }
+
+    /**
+     * Builds a request to make a Pushed Authorization Request (PAR) with JWT-Secured Authorization Requests (JAR), to receive a {@code request_uri} to send to the {@code /authorize} endpoint.
+     * @param request The signed JWT containing the authorization parameters as claims.
+     * @param authorizationDetails A list of maps representing the value of the (optional) {@code authorization_details} parameter, used to perform Rich Authorization Requests. The list will be serialized to JSON and sent on the request.
+     * @see #pushedAuthorizationRequestWithJAR(String)                              
+     * @see Authorization Code Flow with PAR and JAR
+     * @see Authorization Code Flow with Rich Authorization Requests (RAR)
+     * @see RFC 9101
+     * @see RFC 9126
+     * @see RFC 9396
+     * @return a request to execute.
+     */
+    public Request pushedAuthorizationRequestWithJAR(String request, List> authorizationDetails) {
+        Asserts.assertNotNull(request, "request");
+
+        String url = baseUrl
+            .newBuilder()
+            .addPathSegments("oauth/par")
+            .build()
+            .toString();
+
+        FormBodyRequest req = new FormBodyRequest<>(client, null, url, HttpMethod.POST, new TypeReference() {});
+        req.addParameter("client_id", clientId);
+        req.addParameter("request", request);
+        if (Objects.nonNull(this.clientSecret)) {
+            req.addParameter("client_secret", clientSecret);
+        }
+
+        try {
+            if (Objects.nonNull(authorizationDetails)) {
+                String authDetailsJson = getMapper().writeValueAsString(authorizationDetails);
+                req.addParameter("authorization_details", authDetailsJson);
+            }
+        } catch (JsonProcessingException e) {
+            throw new IllegalArgumentException("'authorizationDetails' must be a list that can be serialized to JSON", e);
+        }
+        return req;
+    }
+
     /**
      * Creates an instance of the {@link LogoutUrlBuilder} with the given return-to url.
      * i.e.:
      * 
      * {@code
-     * AuthAPI auth = new AuthAPI("me.auth0.com", "B3c6RYhk1v9SbIJcRIOwu62gIUGsnze", "2679NfkaBn62e6w5E8zNEzjr-yWfkaBne");
-     * String url = auth.logoutUrl("https://me.auth0.com/home", true)
+     * String url = authAPI.logoutUrl("https://me.auth0.com/home", true)
      *      .useFederated(true)
      *      .withAccessToken("A9CvPwFojaBIA9CvI");
      * }
@@ -268,15 +455,15 @@ public LogoutUrlBuilder logoutUrl(String returnToUrl, boolean setClientId) {
      * i.e.:
      * 
      * {@code
-     * AuthAPI auth = new AuthAPI("me.auth0.com", "B3c6RYhk1v9SbIJcRIOwu62gIUGsnze", "2679NfkaBn62e6w5E8zNEzjr-yWfkaBne");
      * try {
-     *      UserInfo result = auth.userInfo("A9CvPwFojaBIA9CvI").execute();
+     *      UserInfo result = authAPI.userInfo("A9CvPwFojaBIA9CvI").execute().getBody();
      * } catch (Auth0Exception e) {
      *      //Something happened
      * }
      * }
      * 
* + * @see Get User Info API docs * @param accessToken a valid access token belonging to an API signed with RS256 algorithm and containing the scope 'openid'. * @return a Request to execute. */ @@ -288,45 +475,130 @@ public Request userInfo(String accessToken) { .addPathSegment("userinfo") .build() .toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", new TypeReference() { + BaseRequest request = new BaseRequest<>(client, null, url, HttpMethod.GET, new TypeReference() { }); request.addHeader("Authorization", "Bearer " + accessToken); return request; } /** - * Request a password reset for the given email and database connection. The response will always be successful even if - * there's no user associated to the given email for that database connection. + * Request a password reset for the given email and database connection, using the client ID configured for this client instance. + * The response will always be successful even if there's no user associated to the given email for that database connection. * i.e.: *
      * {@code
-     * AuthAPI auth = new AuthAPI("me.auth0.com", "B3c6RYhk1v9SbIJcRIOwu62gIUGsnze", "2679NfkaBn62e6w5E8zNEzjr-yWfkaBne");
      * try {
-     *      auth.resetPassword("me@auth0.com", "db-connection").execute();
+     *      authAPI.resetPassword("me@auth0.com", "db-connection").execute().getBody();
      * } catch (Auth0Exception e) {
      *      //Something happened
      * }
      * }
      * 
* + * @see Change Password API docs * @param email the email associated to the database user. * @param connection the database connection where the user was created. * @return a Request to execute. */ public Request resetPassword(String email, String connection) { + return resetPassword(this.clientId, email, connection); + } + + /** + * Request a password reset for the given client ID, email, and database connection. The response will always be successful even if + * there's no user associated to the given email for that database connection. + * i.e.: + *
+     * {@code
+     * try {
+     *      authAPI.resetPassword("CLIENT-ID", "me@auth0.com", "db-connection").execute().getBody();
+     * } catch (Auth0Exception e) {
+     *      //Something happened
+     * }
+     * }
+     * 
+ * + * @see Change Password API docs + * @param clientId the client ID of your client. + * @param email the email associated to the database user. + * @param connection the database connection where the user was created. + * @return a Request to execute. + */ + public Request resetPassword(String clientId, String email, String connection) { + return resetPassword(clientId, email, connection, null); + } + + /** + * Request a password reset for the given client ID, email, database connection and organization ID. The response will always be successful even if + * there's no user associated to the given email for that database connection. + * i.e.: + *
+     * {@code
+     * try {
+     *      authAPI.resetPassword("CLIENT-ID", "me@auth0.com", "db-connection", "ORGANIZATION-ID").execute().getBody();
+     * } catch (Auth0Exception e) {
+     *      //Something happened
+     * }
+     * }
+     * 
+ * + * @see Change Password API docs + * @param clientId the client ID of your client. + * @param email the email associated to the database user. + * @param connection the database connection where the user was created. + * @param organization the organization ID where the user was created. + * @return a Request to execute. + */ + public Request resetPassword(String clientId, String email, String connection, String organization) { Asserts.assertNotNull(email, "email"); Asserts.assertNotNull(connection, "connection"); String url = baseUrl - .newBuilder() - .addPathSegment(PATH_DBCONNECTIONS) - .addPathSegment("change_password") - .build() - .toString(); - VoidRequest request = new VoidRequest(client, url, "POST"); + .newBuilder() + .addPathSegment(PATH_DBCONNECTIONS) + .addPathSegment("change_password") + .build() + .toString(); + VoidRequest request = new VoidRequest(client, null, url, HttpMethod.POST); request.addParameter(KEY_CLIENT_ID, clientId); request.addParameter(KEY_EMAIL, email); request.addParameter(KEY_CONNECTION, connection); + request.addParameter(KEY_ORGANIZATION, organization); + return request; + } + + /** + * Creates a sign up request with the given credentials, phone number and database connection. + * "Requires Username" option must be turned on in the Connection's configuration first. + * i.e.: + *
+     * {@code
+     * try {
+     *      Map fields = new HashMap();
+     *      fields.put("age", "25);
+     *      fields.put("city", "Buenos Aires");
+     *      authAPI.signUp("me@auth0.com", "myself", new char[]{'s','e','c','r','e','t'}, "db-connection", "1234567890")
+     *          .setCustomFields(fields)
+     *          .execute();
+     * } catch (Auth0Exception e) {
+     *      //Something happened
+     * }
+     * }
+     * 
+ * + * @see Signup API docs + * @param email the desired user's email. + * @param username the desired user's username. + * @param password the desired user's password. + * @param connection the database connection where the user is going to be created. + * @param phoneNumber the desired users's phone number. + * @return a Request to configure and execute. + */ + public SignUpRequest signUp(String email, String username, char[] password, String connection, String phoneNumber) { + Asserts.assertNotNull(phoneNumber, "phone number"); + + SignUpRequest request = this.signUp(email, username, password, connection); + request.addParameter(KEY_PHONE_NUMBER, phoneNumber); return request; } @@ -336,12 +608,11 @@ public Request resetPassword(String email, String connection) { * i.e.: *
      * {@code
-     * AuthAPI auth = new AuthAPI("me.auth0.com", "B3c6RYhk1v9SbIJcRIOwu62gIUGsnze", "2679NfkaBn62e6w5E8zNEzjr-yWfkaBne");
      * try {
      *      Map fields = new HashMap();
      *      fields.put("age", "25);
      *      fields.put("city", "Buenos Aires");
-     *      auth.signUp("me@auth0.com", "myself", "topsecret", "db-connection")
+     *      authAPI.signUp("me@auth0.com", "myself", "topsecret", "db-connection")
      *          .setCustomFields(fields)
      *          .execute();
      * } catch (Auth0Exception e) {
@@ -368,12 +639,11 @@ public SignUpRequest signUp(String email, String username, String password, Stri
      * i.e.:
      * 
      * {@code
-     * AuthAPI auth = new AuthAPI("me.auth0.com", "B3c6RYhk1v9SbIJcRIOwu62gIUGsnze", "2679NfkaBn62e6w5E8zNEzjr-yWfkaBne");
      * try {
      *      Map fields = new HashMap();
      *      fields.put("age", "25);
      *      fields.put("city", "Buenos Aires");
-     *      auth.signUp("me@auth0.com", "myself", new char[]{'s','e','c','r','e','t'}, "db-connection")
+     *      authAPI.signUp("me@auth0.com", "myself", new char[]{'s','e','c','r','e','t'}, "db-connection")
      *          .setCustomFields(fields)
      *          .execute();
      * } catch (Auth0Exception e) {
@@ -382,6 +652,7 @@ public SignUpRequest signUp(String email, String username, String password, Stri
      * }
      * 
* + * @see Signup API docs * @param email the desired user's email. * @param username the desired user's username. * @param password the desired user's password. @@ -391,7 +662,7 @@ public SignUpRequest signUp(String email, String username, String password, Stri public SignUpRequest signUp(String email, String username, char[] password, String connection) { Asserts.assertNotNull(username, "username"); - CreateUserRequest request = (CreateUserRequest) this.signUp(email, password, connection); + SignUpRequest request = this.signUp(email, password, connection); request.addParameter(KEY_USERNAME, username); return request; } @@ -401,12 +672,11 @@ public SignUpRequest signUp(String email, String username, char[] password, Stri * i.e.: *
      * {@code
-     * AuthAPI auth = new AuthAPI("me.auth0.com", "B3c6RYhk1v9SbIJcRIOwu62gIUGsnze", "2679NfkaBn62e6w5E8zNEzjr-yWfkaBne");
      * try {
      *      Map fields = new HashMap();
      *      fields.put("age", "25);
      *      fields.put("city", "Buenos Aires");
-     *      auth.signUp("me@auth0.com", "topsecret", "db-connection")
+     *      authAPI.signUp("me@auth0.com", "topsecret", "db-connection")
      *          .setCustomFields(fields)
      *          .execute();
      * } catch (Auth0Exception e) {
@@ -428,15 +698,13 @@ public SignUpRequest signUp(String email, String password, String connection) {
 
     /**
      * Creates a sign up request with the given credentials and database connection.
-     * i.e.:
      * 
      * {@code
-     * AuthAPI auth = new AuthAPI("me.auth0.com", "B3c6RYhk1v9SbIJcRIOwu62gIUGsnze", "2679NfkaBn62e6w5E8zNEzjr-yWfkaBne");
      * try {
      *      Map fields = new HashMap();
      *      fields.put("age", "25);
      *      fields.put("city", "Buenos Aires");
-     *      auth.signUp("me@auth0.com", new char[]{'s','e','c','r','e','t'}, "db-connection")
+     *      authAPI.signUp("me@auth0.com", new char[]{'s','e','c','r','e','t'}, "db-connection")
      *          .setCustomFields(fields)
      *          .execute();
      * } catch (Auth0Exception e) {
@@ -445,6 +713,7 @@ public SignUpRequest signUp(String email, String password, String connection) {
      * }
      * 
* + * @see Signup API docs * @param email the desired user's email. * @param password the desired user's password. * @param connection the database connection where the user is going to be created. @@ -461,7 +730,7 @@ public SignUpRequest signUp(String email, char[] password, String connection) { .addPathSegment("signup") .build() .toString(); - CreateUserRequest request = new CreateUserRequest(client, url); + SignUpRequest request = new SignUpRequest(client, url); request.addParameter(KEY_CLIENT_ID, clientId); request.addParameter(KEY_EMAIL, email); request.addParameter(KEY_PASSWORD, password); @@ -474,9 +743,8 @@ public SignUpRequest signUp(String email, char[] password, String connection) { * i.e.: *
      * {@code
-     * AuthAPI auth = new AuthAPI("me.auth0.com", "B3c6RYhk1v9SbIJcRIOwu62gIUGsnze", "2679NfkaBn62e6w5E8zNEzjr-yWfkaBne");
      * try {
-     *      TokenHolder result = auth.login("me@auth0.com", "topsecret")
+     *      TokenHolder result = authAPI.login("me@auth0.com", "topsecret")
      *          .setScope("openid email nickname")
      *          .execute();
      * } catch (Auth0Exception e) {
@@ -497,20 +765,25 @@ public TokenRequest login(String emailOrUsername, String password) {
 
     /**
      * Creates a log in request using the 'Password' grant and the given credentials.
+     * 
+     * This flow should only be used from highly-trusted applications that cannot do redirects.
+     * If you can use redirect-based flows from your app, we recommend using the Authorization Code Flow instead.
+     * 
      * i.e.:
      * 
      * {@code
-     * AuthAPI auth = new AuthAPI("me.auth0.com", "B3c6RYhk1v9SbIJcRIOwu62gIUGsnze", "2679NfkaBn62e6w5E8zNEzjr-yWfkaBne");
      * try {
-     *      TokenHolder result = auth.login("me@auth0.com", new char[]{'s','e','c','r','e','t})
+     *      TokenHolder result = authAPI.login("me@auth0.com", new char[]{'s','e','c','r','e','t})
      *          .setScope("openid email nickname")
-     *          .execute();
+     *          .execute()
+     *          .getBody();
      * } catch (Auth0Exception e) {
      *      //Something happened
      * }
      * }
      * 
* + * @see Resource Owner Password API docs. * @param emailOrUsername the identity of the user. * @param password the password of the user. * @return a Request to configure and execute. @@ -519,18 +792,12 @@ public TokenRequest login(String emailOrUsername, char[] password) { Asserts.assertNotNull(emailOrUsername, "email or username"); Asserts.assertNotNull(password, "password"); - String url = baseUrl - .newBuilder() - .addPathSegment(PATH_OAUTH) - .addPathSegment(PATH_TOKEN) - .build() - .toString(); - TokenRequest request = new TokenRequest(client, url); + TokenRequest request = new TokenRequest(client, getTokenUrl()); request.addParameter(KEY_CLIENT_ID, clientId); - request.addParameter(KEY_CLIENT_SECRET, clientSecret); request.addParameter(KEY_GRANT_TYPE, "password"); request.addParameter(KEY_USERNAME, emailOrUsername); request.addParameter(KEY_PASSWORD, password); + addClientAuthentication(request, true); return request; } @@ -539,11 +806,11 @@ public TokenRequest login(String emailOrUsername, char[] password) { * Default used realm and audience are defined in the "API Authorization Settings" in the account's advanced settings in the Auth0 Dashboard. *
      * {@code
-     * AuthAPI auth = new AuthAPI("me.auth0.com", "B3c6RYhk1v9SbIJcRIOwu62gIUGsnze", "2679NfkaBn62e6w5E8zNEzjr-yWfkaBne");
      * try {
-     *      TokenHolder result = auth.login("me@auth0.com", "topsecret", "my-realm")
+     *      TokenHolder result = authAPI.login("me@auth0.com", "topsecret", "my-realm")
      *          .setAudience("https://myapi.me.auth0.com/users")
-     *          .execute();
+     *          .execute()
+     *          .getBody();
      * } catch (Auth0Exception e) {
      *      //Something happened
      * }
@@ -564,13 +831,17 @@ public TokenRequest login(String emailOrUsername, String password, String realm)
     /**
      * Creates a log in request using the 'Password Realm' grant and the given credentials.
      * Default used realm and audience are defined in the "API Authorization Settings" in the account's advanced settings in the Auth0 Dashboard.
+     * 
+     * This flow should only be used from highly-trusted applications that cannot do redirects.
+     * If you can use redirect-based flows from your app, we recommend using the Authorization Code Flow instead.
+     * 
      * 
      * {@code
-     * AuthAPI auth = new AuthAPI("me.auth0.com", "B3c6RYhk1v9SbIJcRIOwu62gIUGsnze", "2679NfkaBn62e6w5E8zNEzjr-yWfkaBne");
      * try {
-     *      TokenHolder result = auth.login("me@auth0.com", new char[]{'s','e','c','r','e','t'}, "my-realm")
+     *      TokenHolder result = authAPI.login("me@auth0.com", new char[]{'s','e','c','r','e','t'}, "my-realm")
      *          .setAudience("https://myapi.me.auth0.com/users")
-     *          .execute();
+     *          .execute()
+     *          .getBody();
      * } catch (Auth0Exception e) {
      *      //Something happened
      * }
@@ -581,37 +852,33 @@ public TokenRequest login(String emailOrUsername, String password, String realm)
      * @param password        the password of the user.
      * @param realm           the realm to use.
      * @return a Request to configure and execute.
+     * @see Resource Owner Password API docs.
      */
     public TokenRequest login(String emailOrUsername, char[] password, String realm) {
         Asserts.assertNotNull(emailOrUsername, "email or username");
         Asserts.assertNotNull(password, "password");
         Asserts.assertNotNull(realm, "realm");
 
-        String url = baseUrl
-                .newBuilder()
-                .addPathSegment(PATH_OAUTH)
-                .addPathSegment(PATH_TOKEN)
-                .build()
-                .toString();
-        TokenRequest request = new TokenRequest(client, url);
+        TokenRequest request = new TokenRequest(client, getTokenUrl());
         request.addParameter(KEY_CLIENT_ID, clientId);
-        request.addParameter(KEY_CLIENT_SECRET, clientSecret);
         request.addParameter(KEY_GRANT_TYPE, "http://auth0.com/oauth/grant-type/password-realm");
         request.addParameter(KEY_USERNAME, emailOrUsername);
         request.addParameter(KEY_PASSWORD, password);
         request.addParameter(KEY_REALM, realm);
+        addClientAuthentication(request, true);
         return request;
     }
 
     /**
      * Creates a login request using the Passwordless grant type.
+     * Confidential clients (Regular Web Apps) must have a client secret configured on this {@code AuthAPI} instance.
      *
      * 
      * {@code
-     * AuthAPI auth = new AuthAPI("me.auth0.com", "B3c6RYhk1v9SbIJcRIOwu62gIUGsnze", "2679NfkaBn62e6w5E8zNEzjr-yWfkaBne");
      * try {
-     *      TokenHolder result = auth.exchangePasswordlessOtp("user@domain.com", "email", new char[]{'c','o','d','e'})
-     *          .execute();
+     *      TokenHolder result = authAPI.exchangePasswordlessOtp("user@domain.com", "email", new char[]{'c','o','d','e'})
+     *          .execute()
+     *          .getBody();
      * } catch (Auth0Exception e) {
      *      // Something happened
      * }
@@ -625,6 +892,7 @@ public TokenRequest login(String emailOrUsername, char[] password, String realm)
      * @return A request to configure and execute
      *
      * @see Using Passwordless APIs
+     * @see Passwordless Authenticate User API docs
      * @see com.auth0.client.auth.AuthAPI#startPasswordlessEmailFlow(String, PasswordlessEmailType)
      * @see com.auth0.client.auth.AuthAPI#startPasswordlessSmsFlow(String)
      */
@@ -633,65 +901,83 @@ public TokenRequest exchangePasswordlessOtp(String emailOrPhone, String realm, c
         Asserts.assertNotNull(realm, "realm");
         Asserts.assertNotNull(otp, "otp");
 
-        String url = baseUrl
-                .newBuilder()
-                .addPathSegment(PATH_OAUTH)
-                .addPathSegment(PATH_TOKEN)
-                .build()
-                .toString();
-        TokenRequest request = new TokenRequest(client, url);
+        TokenRequest request = new TokenRequest(client, getTokenUrl());
         request.addParameter(KEY_CLIENT_ID, clientId);
-        request.addParameter(KEY_CLIENT_SECRET, clientSecret);
         request.addParameter(KEY_GRANT_TYPE, "http://auth0.com/oauth/grant-type/passwordless/otp");
         request.addParameter(KEY_USERNAME, emailOrPhone);
         request.addParameter(KEY_REALM, realm);
         request.addParameter(KEY_OTP, otp);
+        addClientAuthentication(request, false);
         return request;
     }
 
     /**
      * Creates a request to get a Token for the given audience using the 'Client Credentials' grant.
      * Default used realm is defined in the "API Authorization Settings" in the account's advanced settings in the Auth0 Dashboard.
+     * This operation requires that a client secret be configured for the {@code AuthAPI} client.
      * 
      * {@code
-     * AuthAPI auth = new AuthAPI("me.auth0.com", "B3c6RYhk1v9SbIJcRIOwu62gIUGsnze", "2679NfkaBn62e6w5E8zNEzjr-yWfkaBne");
      * try {
-     *      TokenHolder result = auth.requestToken("https://myapi.me.auth0.com/users")
+     *      TokenHolder result = authAPI.requestToken("https://myapi.me.auth0.com/users")
      *          .setRealm("my-realm")
-     *          .execute();
+     *          .execute()
+     *          .getBody();
      * } catch (Auth0Exception e) {
      *      //Something happened
      * }
      * }
      * 
* + * @see Client Credentials Flow API docs * @param audience the audience of the API to request access to. * @return a Request to configure and execute. */ public TokenRequest requestToken(String audience) { + return requestToken(audience, null); + } + + /** + * Creates a request to get a Token for the given audience using the 'Client Credentials' grant. + * Default used realm is defined in the "API Authorization Settings" in the account's advanced settings in the Auth0 Dashboard. + * This operation requires that a client secret be configured for the {@code AuthAPI} client. + *
+     * {@code
+     * try {
+     *      TokenHolder result = authAPI.requestToken("https://myapi.me.auth0.com/users", "org_123")
+     *          .execute()
+     *          .getBody();
+     * } catch (Auth0Exception e) {
+     *      //Something happened
+     * }
+     * }
+     * 
+ * + * @see Client Credentials Flow API docs + * @param audience the audience of the API to request access to. + * @param org the organization name or ID to be included in the request. + * @return a Request to configure and execute. + */ + public TokenRequest requestToken(String audience, String org) { Asserts.assertNotNull(audience, "audience"); - String url = baseUrl - .newBuilder() - .addPathSegment(PATH_OAUTH) - .addPathSegment(PATH_TOKEN) - .build() - .toString(); - TokenRequest request = new TokenRequest(client, url); + TokenRequest request = new TokenRequest(client, getTokenUrl()); request.addParameter(KEY_CLIENT_ID, clientId); - request.addParameter(KEY_CLIENT_SECRET, clientSecret); request.addParameter(KEY_GRANT_TYPE, "client_credentials"); request.addParameter(KEY_AUDIENCE, audience); + if (org != null && !org.trim().isEmpty()) { + request.addParameter(KEY_ORGANIZATION, org); + } + addClientAuthentication(request, true); return request; } /** * Creates a request to revoke an existing Refresh Token. + * Confidential clients (Regular Web Apps) must have a client secret configured on this {@code AuthAPI} instance. *
      * {@code
-     * AuthAPI auth = new AuthAPI("me.auth0.com", "B3c6RYhk1v9SbIJcRIOwu62gIUGsnze", "2679NfkaBn62e6w5E8zNEzjr-yWfkaBne");
      * try {
-     *      auth.revokeToken("ej2E8zNEzjrcSD2edjaE")
+     *      authAPI.revokeToken("ej2E8zNEzjrcSD2edjaE")
      *          .execute();
      * } catch (Auth0Exception e) {
      *      //Something happened
@@ -699,6 +985,7 @@ public TokenRequest requestToken(String audience) {
      * }
      * 
* + * @see Revoke refresh token API docs * @param refreshToken the refresh token to revoke. * @return a Request to execute. */ @@ -711,95 +998,131 @@ public Request revokeToken(String refreshToken) { .addPathSegment(PATH_REVOKE) .build() .toString(); - VoidRequest request = new VoidRequest(client, url, "POST"); + VoidRequest request = new VoidRequest(client, null, url, HttpMethod.POST); request.addParameter(KEY_CLIENT_ID, clientId); - request.addParameter(KEY_CLIENT_SECRET, clientSecret); request.addParameter(KEY_TOKEN, refreshToken); + addClientAuthentication(request, false); return request; } /** - * Creates a request to renew the authentication and get fresh new credentials using a valid Refresh Token and the 'refresh_token' grant. + * Creates a request to renew the authentication and get fresh new credentials using a valid Refresh Token and the + * {@code refresh_token} grant. + * Confidential clients (Regular Web Apps) must have a client secret configured on this {@code AuthAPI} instance. + * *
      * {@code
-     * AuthAPI auth = new AuthAPI("me.auth0.com", "B3c6RYhk1v9SbIJcRIOwu62gIUGsnze", "2679NfkaBn62e6w5E8zNEzjr-yWfkaBne");
      * try {
-     *      TokenHolder result = auth.renewAuth("ej2E8zNEzjrcSD2edjaE")
-     *          .execute();
+     *      TokenHolder result = authAPI.renewAuth("ej2E8zNEzjrcSD2edjaE")
+     *          .execute()
+     *          .getBody();
      * } catch (Auth0Exception e) {
      *      //Something happened
      * }
      * }
      * 
* + * @see Refresh Token API docs * @param refreshToken the refresh token to use to get fresh new credentials. * @return a Request to configure and execute. */ public TokenRequest renewAuth(String refreshToken) { Asserts.assertNotNull(refreshToken, "refresh token"); - String url = baseUrl - .newBuilder() - .addPathSegment(PATH_OAUTH) - .addPathSegment(PATH_TOKEN) - .build() - .toString(); - TokenRequest request = new TokenRequest(client, url); + TokenRequest request = new TokenRequest(client, getTokenUrl()); request.addParameter(KEY_CLIENT_ID, clientId); - request.addParameter(KEY_CLIENT_SECRET, clientSecret); request.addParameter(KEY_GRANT_TYPE, "refresh_token"); request.addParameter(KEY_REFRESH_TOKEN, refreshToken); + addClientAuthentication(request, false); return request; } /** * Creates a request to exchange the code obtained in the /authorize call using the 'Authorization Code' grant. + * This operation requires the {@code AuthAPI} instance to have a client secret configured. *
      * {@code
-     * AuthAPI auth = new AuthAPI("me.auth0.com", "B3c6RYhk1v9SbIJcRIOwu62gIUGsnze", "2679NfkaBn62e6w5E8zNEzjr-yWfkaBne");
      * try {
-     *      TokenHolder result = auth.exchangeCode("SnWoFLMzApDskr", "https://me.auth0.com/callback")
+     *      TokenHolder result = authAPI.exchangeCode("SnWoFLMzApDskr", "https://me.auth0.com/callback")
      *          .setScope("openid name nickname")
-     *          .execute();
+     *          .execute()
+     *          .getBody();
      * } catch (Auth0Exception e) {
      *      //Something happened
      * }
      * }
      * 
* + * @see Authorization Code Flow API docs * @param code the authorization code received from the /authorize call. * @param redirectUri the redirect uri sent on the /authorize call. * @return a Request to configure and execute. */ public TokenRequest exchangeCode(String code, String redirectUri) { + return exchangeCode(code, redirectUri, true); + } + + /** + * Creates a request to exchange the code obtained from the {@code /authorize} call using the Authorization Code + * with PKCE grant. + * Confidential clients (Regular Web Apps) must have a client secret configured on this {@code AuthAPI} instance. + *
+     * {@code
+     * AuthAPI auth = AuthAPI.newBuilder("DOMAIN", "CLIENT-ID", "CLIENT-SECRET").build();
+     *
+     * SecureRandom sr = new SecureRandom();
+     * byte[] code = new byte[32];
+     * sr.nextBytes(code);
+     * String verifier = Base64.getUrlEncoder().withoutPadding().encodeToString(code);
+     *
+     * byte[] bytes = verifier.getBytes("US-ASCII");
+     * MessageDigest md = MessageDigest.getInstance("SHA-256");
+     * md.update(bytes, 0, bytes.length);
+     * byte[] digest = md.digest();
+     * String challenge = Base64.getUrlEncoder().withoutPadding().encodeToString(digest);
+     *
+     * // generate authorize URL with code challenge derived from verifier
+     * String url = auth.authorizeUrl("https://me.auth0.com/callback")
+     *      .withCodeChallenge(challenge)
+     *      .build();
+     *
+     * // on redirect, exchange code and verify challenge
+     * try {
+     *      TokenHolder result = auth.exchangeCodeWithVerifier("CODE", verifier, "https://me.auth0.com/callback")
+     *          .setScope("openid name nickname")
+     *          .execute();
+     * } catch (Auth0Exception e) {
+     *      // Something happened
+     * }
+     * }
+     * 
+ * + * @param code the authorization code received from the {@code /authorize} call. + * @param verifier the cryptographically random key that was used to generate the {@code code_challenge} passed to + * {@code /authorize} + * @param redirectUri the redirect uri sent on the /authorize call. + * @return a Request to configure and execute. + */ + public TokenRequest exchangeCodeWithVerifier(String code, String verifier, String redirectUri) { Asserts.assertNotNull(code, "code"); Asserts.assertNotNull(redirectUri, "redirect uri"); + Asserts.assertNotNull(verifier, "verifier"); - String url = baseUrl - .newBuilder() - .addPathSegment(PATH_OAUTH) - .addPathSegment(PATH_TOKEN) - .build() - .toString(); - TokenRequest request = new TokenRequest(client, url); - request.addParameter(KEY_CLIENT_ID, clientId); - request.addParameter(KEY_CLIENT_SECRET, clientSecret); - request.addParameter(KEY_GRANT_TYPE, "authorization_code"); - request.addParameter("code", code); - request.addParameter("redirect_uri", redirectUri); + TokenRequest request = exchangeCode(code, redirectUri, false); + request.addParameter("code_verifier", verifier); return request; } /** * Create a request to send an email containing a link or a code to begin authentication with Passwordless connections. - * + * Confidential clients (Regular Web Apps) must have a client secret configured on this {@code AuthAPI} instance. *
      * {@code
-     * AuthAPI auth = new AuthAPI("me.auth0.com", "B3c6RYhk1v9SbIJcRIOwu62gIUGsnze", "2679NfkaBn62e6w5E8zNEzjr-yWfkaBne");
      * try {
-     *      PasswordlessEmailResponse result = auth.startPasswordlessEmailFlow("user@domain.com", PasswordlessEmailType.CODE)
-     *          .execute();
+     *      PasswordlessEmailResponse result = authAPI.startPasswordlessEmailFlow("user@domain.com", PasswordlessEmailType.CODE)
+     *          .execute()
+     *          .getBody();
      * } catch (Auth0Exception e) {
      *      // Something happened
      * }
@@ -814,7 +1137,7 @@ public TokenRequest exchangeCode(String code, String redirectUri) {
      * @see Passwordless Authentication with Email documentation
      * @see Get code or link API reference documentation
      */
-    public CustomRequest startPasswordlessEmailFlow(String email, PasswordlessEmailType type) {
+    public BaseRequest startPasswordlessEmailFlow(String email, PasswordlessEmailType type) {
         Asserts.assertNotNull(email, "email");
         Asserts.assertNotNull(type, "type");
 
@@ -825,25 +1148,25 @@ public CustomRequest startPasswordlessEmailFlow(Strin
                 .build()
                 .toString();
 
-        CustomRequest request = new CustomRequest<>(client, url, "POST", new TypeReference() {
+        BaseRequest request = new BaseRequest<>(client, null, url, HttpMethod.POST, new TypeReference() {
         });
         request.addParameter(KEY_CLIENT_ID, clientId);
-        request.addParameter(KEY_CLIENT_SECRET, clientSecret);
         request.addParameter(KEY_CONNECTION, "email");
         request.addParameter(KEY_EMAIL, email);
         request.addParameter("send", type.getType());
+        addClientAuthentication(request, false);
         return request;
     }
 
     /**
      * Create a request to send a text message containing a code to begin authentication with Passwordless connections.
-     *
+     * Confidential clients (Regular Web Apps) must have a client secret configured on this {@code AuthAPI} instance.
      * 
      * {@code
-     * AuthAPI auth = new AuthAPI("me.auth0.com", "B3c6RYhk1v9SbIJcRIOwu62gIUGsnze", "2679NfkaBn62e6w5E8zNEzjr-yWfkaBne");
      * try {
-     *      PasswordlessSmsResponse result = auth.startPasswordlessSmsFlow("+16511234567")
-     *          .execute();
+     *      PasswordlessSmsResponse result = authAPI.startPasswordlessSmsFlow("+16511234567")
+     *          .execute()
+     *          .getBody();
      * } catch (Auth0Exception e) {
      *      // Something happened
      * }
@@ -857,7 +1180,7 @@ public CustomRequest startPasswordlessEmailFlow(Strin
      * @see Passwordless Authentication with SMS documentation
      * @see Get code or link API reference documentation
      */
-    public CustomRequest startPasswordlessSmsFlow(String phoneNumber) {
+    public BaseRequest startPasswordlessSmsFlow(String phoneNumber) {
         Asserts.assertNotNull(phoneNumber, "phoneNumber");
 
         String url = baseUrl
@@ -867,24 +1190,24 @@ public CustomRequest startPasswordlessSmsFlow(String ph
                 .build()
                 .toString();
 
-        CustomRequest request = new CustomRequest<>(client, url, "POST", new TypeReference() {
+        BaseRequest request = new BaseRequest<>(client, null, url, HttpMethod.POST, new TypeReference() {
         });
         request.addParameter(KEY_CLIENT_ID, clientId);
-        request.addParameter(KEY_CLIENT_SECRET, clientSecret);
         request.addParameter(KEY_CONNECTION, "sms");
         request.addParameter("phone_number", phoneNumber);
+        addClientAuthentication(request, false);
         return request;
     }
 
     /**
      * Creates a request to exchange the mfa token and one-time password (OTP) to authenticate a user with an MFA OTP Authenticator.
-     *
+     * Confidential clients (Regular Web Apps) must have a client secret configured on this {@code AuthAPI} instance.
      * 
      * {@code
-     * AuthAPI auth = new AuthAPI("me.auth0.com", "B3c6RYhk1v9SbIJcRIOwu62gIUGsnze", "2679NfkaBn62e6w5E8zNEzjr-yWfkaBne");
      * try {
-     *      TokenHolder result = auth.exchangeMfaOtp("the-mfa-token", new char[]{'a','n','o','t','p'})
-     *          .execute();
+     *      TokenHolder result = authAPI.exchangeMfaOtp("the-mfa-token", new char[]{'a','n','o','t','p'})
+     *          .execute()
+     *          .getBody();
      * } catch (Auth0Exception e) {
      *      //Something happened
      * }
@@ -902,18 +1225,443 @@ public TokenRequest exchangeMfaOtp(String mfaToken, char[] otp) {
         Asserts.assertNotNull(mfaToken, "mfa token");
         Asserts.assertNotNull(otp, "otp");
 
-        String url = baseUrl
-                .newBuilder()
-                .addPathSegment(PATH_OAUTH)
-                .addPathSegment(PATH_TOKEN)
-                .build()
-                .toString();
-        TokenRequest request = new TokenRequest(client, url);
+        TokenRequest request = new TokenRequest(client, getTokenUrl());
         request.addParameter(KEY_CLIENT_ID, clientId);
-        request.addParameter(KEY_CLIENT_SECRET, clientSecret);
         request.addParameter(KEY_GRANT_TYPE, "http://auth0.com/oauth/grant-type/mfa-otp");
         request.addParameter(KEY_MFA_TOKEN, mfaToken);
         request.addParameter(KEY_OTP, otp);
+        addClientAuthentication(request, false);
+        return request;
+    }
+
+    /**
+     * Creates a request to exchange the mfa token and an out-of-band (OOB) challenge (either Push notification, SMS, or Voice).
+     * Confidential clients (Regular Web Apps) must have a client secret configured on this {@code AuthAPI} instance.
+     * 
+     * {@code
+     * try {
+     *      TokenHolder result = authAPI.exchangeMfaOob("the-mfa-token", new char[]{'a','n','o','t','p'}, new char[]{'b','i','n','d','c','o','d','e'})
+     *          .execute()
+     *          .getBody();
+     * } catch (Auth0Exception e) {
+     *      //Something happened
+     * }
+     * }
+     * 
+ * + * @param mfaToken the mfa_token received from the mfa_required error that occurred during login. Must not be null. + * @param oobCode the OOB Code provided by the user. Must not be null. + * @param bindingCode A code used to bind the side channel (used to deliver the challenge) with the main channel you are using to authenticate. This is usually an OTP-like code delivered as part of the challenge message. May be null. + * + * @return a Request to configure and execute. + * + * @see Verify with Out-of-band (OOB) API documentation + */ + public TokenRequest exchangeMfaOob(String mfaToken, char[] oobCode, char[] bindingCode) { + Asserts.assertNotNull(mfaToken, "mfa token"); + Asserts.assertNotNull(oobCode, "OOB code"); + + TokenRequest request = new TokenRequest(client, getTokenUrl()); + request.addParameter(KEY_CLIENT_ID, clientId); + request.addParameter(KEY_GRANT_TYPE, "http://auth0.com/oauth/grant-type/mfa-oob"); + request.addParameter(KEY_MFA_TOKEN, mfaToken); + request.addParameter("oob_code", oobCode); + + if (Objects.nonNull(bindingCode) && bindingCode.length > 0) { + request.addParameter("binding_code", bindingCode); + } + + addClientAuthentication(request, false); + return request; + } + + /** + * Creates a request to exchange the mfa token using a recovery code. + * Confidential clients (Regular Web Apps) must have a client secret configured on this {@code AuthAPI} instance. + *
+     * {@code
+     * try {
+     *      TokenHolder result = authAPI.exchangeMfaRecoveryCode("the-mfa-token", new char[]{'c','o','d','e'})
+     *          .execute()
+     *          .getBody();
+     * } catch (Auth0Exception e) {
+     *      //Something happened
+     * }
+     * }
+     * 
+ * + * @param mfaToken the mfa_token received from the mfa_required error that occurred during login. Must not be null. + * @param recoveryCode the recovery code provided by the user. Must not be null. + * @return a Request to configure and execute. + * + * @see Verify with a recovery code API documentation + */ + public TokenRequest exchangeMfaRecoveryCode(String mfaToken, char[] recoveryCode) { + Asserts.assertNotNull(mfaToken, "mfa token"); + Asserts.assertNotNull(recoveryCode, "recovery code"); + + TokenRequest request = new TokenRequest(client, getTokenUrl()); + request.addParameter(KEY_CLIENT_ID, clientId); + request.addParameter(KEY_GRANT_TYPE, "http://auth0.com/oauth/grant-type/mfa-recovery-code"); + request.addParameter(KEY_MFA_TOKEN, mfaToken); + request.addParameter("recovery_code", recoveryCode); + + addClientAuthentication(request, false); + return request; + } + + /** + * Request a challenge for multi-factor authentication (MFA) based on the challenge types supported by the application and user. + * Confidential clients (Regular Web Apps) must have a client secret configured on this {@code AuthAPI} instance. + *
+     * {@code
+     * try {
+     *      MfaChallengeResponse result = authAPI.mfaChallengeRequest("the-mfa-token", "otp", "authenticator-id")
+     *          .execute()
+     *          .getBody();
+     * } catch (Auth0Exception e) {
+     *      //Something happened
+     * }
+     * }
+     * 
+ * + * @param mfaToken The token received from mfa_required error. Must not be null. + * @param challengeType A whitespace-separated list of the challenges types accepted by your application. + * @param authenticatorId The ID of the authenticator to challenge. + * @return a Request to execute. + * @see Challenge Request API documentation + */ + public Request mfaChallengeRequest(String mfaToken, String challengeType, String authenticatorId) { + Asserts.assertNotNull(mfaToken, "mfa token"); + + String url = baseUrl + .newBuilder() + .addPathSegment("mfa") + .addPathSegment("challenge") + .build() + .toString(); + + BaseRequest request = new BaseRequest<>(client, null, url, HttpMethod.POST, new TypeReference() { + }); + + request.addParameter(KEY_MFA_TOKEN, mfaToken); + request.addParameter(KEY_CLIENT_ID, clientId); + addClientAuthentication(request, false); + if (Objects.nonNull(challengeType)) { + request.addParameter("challenge_type", challengeType); + } + if (Objects.nonNull(authenticatorId)) { + request.addParameter("authenticator_id", authenticatorId); + } + return request; + } + + /** + * Associates or adds a new OTP authenticator for multi-factor authentication (MFA). + * Confidential clients (Regular Web Apps) must have a client secret configured on this {@code AuthAPI} instance. + *
+     * {@code
+     * try {
+     *      CreatedOTPResponse result = authAPI.addOTPAuthenticator("the-mfa-token")
+     *          .execute()
+     *          .getBody();
+     * } catch (Auth0Exception e) {
+     *      //Something happened
+     * }
+     * }
+     * 
+ * + * @param mfaToken The token received from mfa_required error. Must not be null. + * @return a Request to execute. + * @see Add an Authenticator API documentation + */ + public Request addOtpAuthenticator(String mfaToken) { + Asserts.assertNotNull(mfaToken, "mfa token"); + + String url = baseUrl + .newBuilder() + .addPathSegment("mfa") + .addPathSegment("associate") + .build() + .toString(); + + BaseRequest request = new BaseRequest<>(client, null, url, HttpMethod.POST, new TypeReference() { + }); + + request.addParameter("authenticator_types", Collections.singletonList("otp")); + request.addParameter(KEY_CLIENT_ID, clientId); + addClientAuthentication(request, false); + request.addHeader("Authorization", "Bearer " + mfaToken); + return request; + } + + + private BaseRequest createBaseOobRequest(String mfaToken, List oobChannels) { + String url = baseUrl + .newBuilder() + .addPathSegment("mfa") + .addPathSegment("associate") + .build() + .toString(); + + BaseRequest request = new BaseRequest<>(client, null, url, HttpMethod.POST, new TypeReference() { + }); + + request.addParameter("authenticator_types", Collections.singletonList("oob")); + request.addParameter("oob_channels", oobChannels); + request.addParameter(KEY_CLIENT_ID, clientId); + addClientAuthentication(request, false); + request.addHeader("Authorization", "Bearer " + mfaToken); + + return request; + } + + /** + * Associates or adds a new OOB authenticator for multi-factor authentication (MFA). + * Confidential clients (Regular Web Apps) must have a client secret configured on this {@code AuthAPI} instance. + *
+     * {@code
+     * try {
+     *      CreatedOobResponse result = authAPI.addOobAuthenticator("the-mfa-token", Collections.singletonList("sms"), "phone-number")
+     *          .execute()
+     *          .getBody();
+     * } catch (Auth0Exception e) {
+     *      //Something happened
+     * }
+     * }
+     * 
+ * + * @param mfaToken The token received from mfa_required error. Must not be null. + * @param oobChannels The type of OOB channels supported by the client. Must not be null. + * @param phoneNumber The phone number for "sms" or "voice" channels. May be null if not using "sms" or "voice". + * @return a Request to execute. + * @see Add an Authenticator API documentation + * @deprecated Use {@linkplain #addOobAuthenticator(String, List, String, String)} instead. + */ + @Deprecated + public Request addOobAuthenticator(String mfaToken, List oobChannels, String phoneNumber) { + Asserts.assertNotNull(mfaToken, "mfa token"); + Asserts.assertNotNull(oobChannels, "OOB channels"); + if (oobChannels.contains("sms") || oobChannels.contains("voice")) { + Asserts.assertNotNull(phoneNumber, "phone number"); + } + + BaseRequest request = createBaseOobRequest(mfaToken, oobChannels); + + if (phoneNumber != null) { + request.addParameter("phone_number", phoneNumber); + } + return request; } + + /** + * Associates or adds a new OOB authenticator for multi-factor authentication (MFA). + * Confidential clients (Regular Web Apps) must have a client secret configured on this {@code AuthAPI} instance. + *
+     * {@code
+     * try {
+     *      CreatedOobResponse result = authAPI.addOobAuthenticator("the-mfa-token", Arrays.asList("sms", "email"), "phone-number", "email-address")
+     *          .execute()
+     *          .getBody();
+     * } catch (Auth0Exception e) {
+     *      //Something happened
+     * }
+     * }
+     * 
+ * + * @param mfaToken The token received from mfa_required error. Must not be null. + * @param oobChannels The type of OOB channels supported by the client. Must not be null. + * @param phoneNumber The phone number for "sms" or "voice" channels. May be null if not using "sms" or "voice". + * @param emailAddress The email address for "email" channel. May be null if not using "email". + * @return a Request to execute. + * @see Enroll with SMS or voice + */ + public Request addOobAuthenticator(String mfaToken, List oobChannels, String phoneNumber, String emailAddress) { + Asserts.assertNotNull(mfaToken, "mfa token"); + Asserts.assertNotNull(oobChannels, "OOB channels"); + if (oobChannels.contains("sms") || oobChannels.contains("voice")) { + Asserts.assertNotNull(phoneNumber, "phone number"); + } + if (oobChannels.contains("email")) { + Asserts.assertNotNull(emailAddress, "email address"); + } + + BaseRequest request = createBaseOobRequest(mfaToken, oobChannels); + if (phoneNumber != null) { + request.addParameter("phone_number", phoneNumber); + } + if (emailAddress != null) { + request.addParameter("email", emailAddress); + } + + return request; + } + + /** + * Returns a list of authenticators associated with your application. + *
+     * {@code
+     * try {
+     *      List result = authAPI.listAuthenticators("token")
+     *          .execute()
+     *          .getBody();
+     * } catch (Auth0Exception e) {
+     *      //Something happened
+     * }
+     * }
+     * 
+ * + * @param accessToken The Access Token obtained during login. The token must possess a scope of {@code read:authenticators} + * and an audience of {@code https://YOUR_DOMAIN/mfa/} + * @return a Request to execute. + * @see List authenticators API documentation + */ + public Request> listAuthenticators(String accessToken) { + Asserts.assertNotNull(accessToken, "access token"); + + String url = baseUrl + .newBuilder() + .addPathSegment("mfa") + .addPathSegment("authenticators") + .build() + .toString(); + + BaseRequest> request = new BaseRequest<>(client, null, url, HttpMethod.GET, new TypeReference>() { + }); + + request.addHeader("Authorization", "Bearer " + accessToken); + return request; + } + + /** + * Deletes an associated authenticator using its ID. + *
+     * {@code
+     * try {
+     *    authAPI.deleteAuthenticator("token", "deviceId")
+     *          .execute()
+     *          .getBody();
+     * } catch (Auth0Exception e) {
+     *      //Something happened
+     * }
+     * }
+     * 
+ * + * @param accessToken The Access Token obtained during login. The token must possess a scope of {@code remove:authenticators} + * and an audience of {@code https://YOUR_DOMAIN/mfa/} + * @param authenticatorId The unique identifier associated with the authenticator. We can obtain the authenticatorIds by making a + * call to {@code listAuthenticators} method in this api. + * @return a Request to execute. + * @see Delete authenticators API documentation + */ + public Request deleteAuthenticator(String accessToken, String authenticatorId) { + Asserts.assertNotNull(accessToken, "access token"); + Asserts.assertNotNull(authenticatorId, "authenticator id"); + + String url = baseUrl + .newBuilder() + .addPathSegment("mfa") + .addPathSegment("authenticators") + .addPathSegment(authenticatorId) + .build() + .toString(); + + VoidRequest request = new VoidRequest(client, null, url, HttpMethod.DELETE); + request.addHeader("Authorization", "Bearer " + accessToken); + return request; + } + + private TokenRequest exchangeCode(String code, String redirectUri, boolean secretRequired) { + Asserts.assertNotNull(code, "code"); + Asserts.assertNotNull(redirectUri, "redirect uri"); + + TokenRequest request = new TokenRequest(client, getTokenUrl()); + request.addParameter(KEY_CLIENT_ID, clientId); + request.addParameter(KEY_GRANT_TYPE, "authorization_code"); + request.addParameter("code", code); + request.addParameter("redirect_uri", redirectUri); + addClientAuthentication(request, secretRequired); + return request; + } + + private String getTokenUrl() { + return baseUrl + .newBuilder() + .addPathSegment(PATH_OAUTH) + .addPathSegment(PATH_TOKEN) + .build() + .toString(); + } + + private void addClientAuthentication(BaseRequest request, boolean required) { + if (required && (this.clientSecret == null && this.clientAssertionSigner == null)) { + throw new IllegalStateException("A client secret or client assertion signing key is required for this operation"); + } + + if (Objects.nonNull(this.clientAssertionSigner)) { + request.addParameter(KEY_CLIENT_ASSERTION, this.clientAssertionSigner.createSignedClientAssertion(clientId, baseUrl.toString(), clientId)); + request.addParameter(KEY_CLIENT_ASSERTION_TYPE, "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"); + } else if (Objects.nonNull(this.clientSecret)) { + request.addParameter(KEY_CLIENT_SECRET, clientSecret); + } + } + + + /** + * Builder for {@link AuthAPI} API client instances. + */ + public static class Builder { + private final String domain; + private final String clientId; + private String clientSecret; + private ClientAssertionSigner clientAssertionSigner; + private Auth0HttpClient httpClient; + + public Builder(String domain, String clientId) { + this.domain = domain; + this.clientId = clientId; + this.clientSecret = null; + } + + /** + * Configure the client with a client secret. + * @param clientSecret the client secret of your application. + * @return the builder instance. + */ + public Builder withClientSecret(String clientSecret) { + this.clientSecret = clientSecret; + return this; + } + + /** + * Configure the client with a client assertion signer. + * @param clientAssertionSigner the client assertion signer to create the signed client assertion. + * @return the builder instance. + */ + public Builder withClientAssertionSigner(ClientAssertionSigner clientAssertionSigner) { + this.clientAssertionSigner = clientAssertionSigner; + return this; + } + + /** + * Configure the client with an {@link Auth0HttpClient}. + * @param httpClient the HTTP client to use when making requests. + * @return the builder instance. + * @see DefaultHttpClient + */ + public Builder withHttpClient(Auth0HttpClient httpClient) { + this.httpClient = httpClient; + return this; + } + + /** + * Builds an {@link AuthAPI} instance using this builder's configuration. + * @return the configured {@code AuthAPI} instance. + */ + public AuthAPI build() { + return new AuthAPI(domain, clientId, clientSecret, clientAssertionSigner, + Objects.nonNull(httpClient) ? httpClient : DefaultHttpClient.newBuilder().build()); + } + } } diff --git a/src/main/java/com/auth0/client/auth/AuthorizeUrlBuilder.java b/src/main/java/com/auth0/client/auth/AuthorizeUrlBuilder.java index 68eae1f32..1ce833a5f 100644 --- a/src/main/java/com/auth0/client/auth/AuthorizeUrlBuilder.java +++ b/src/main/java/com/auth0/client/auth/AuthorizeUrlBuilder.java @@ -109,7 +109,7 @@ public AuthorizeUrlBuilder withResponseType(String responseType) { /** * Sets the organization query string parameter value used to login to an organization. * - * @param organization The ID of the organization to log the user in to. + * @param organization The ID or name of the organization to log the user in to. * @return the builder instance. */ public AuthorizeUrlBuilder withOrganization(String organization) { @@ -145,6 +145,22 @@ public AuthorizeUrlBuilder withParameter(String name, String value) { return this; } + /** + * Sets the {@code code_challenge} parameter used when using the Authorization Code Flow with Proof of Code Exchange (PKCE). + * + * @param challenge the generated challenge from a {@code code_verifier} + * @return the builder instance. + * + * @see Authentication API docuementation + * @see Authorization Code Flow with Proof of Code Exchange (PKCE) + */ + public AuthorizeUrlBuilder withCodeChallenge(String challenge) { + assertNotNull(challenge, "challenge"); + parameters.put("code_challenge", challenge); + parameters.put("code_challenge_method", "S256"); + return this; + } + /** * Creates a string representation of the URL with the configured parameters. * diff --git a/src/main/java/com/auth0/client/auth/ClientAssertionSigner.java b/src/main/java/com/auth0/client/auth/ClientAssertionSigner.java new file mode 100644 index 000000000..679c061f4 --- /dev/null +++ b/src/main/java/com/auth0/client/auth/ClientAssertionSigner.java @@ -0,0 +1,20 @@ +package com.auth0.client.auth; + +/** + * Responsible for creating a signed client assertion used to authenticate to the Authentication API + * + * @see OpenID Connect Core Specification + */ +public interface ClientAssertionSigner { + + /** + * Creates a signed JWT representing a client assertion used to authenticate to the Authentication API. + * + * @param issuer the Issuer. This MUST contain the client_id of the OAuth Client. + * @param audience the audience that identifies the Authorization Server as an intended audience. + * @param subject the Subject. This MUST contain the client_id of the OAuth Client. + + * @return a signed JWT representing the client assertion. + */ + String createSignedClientAssertion(String issuer, String audience, String subject); +} diff --git a/src/main/java/com/auth0/client/auth/RSAClientAssertionSigner.java b/src/main/java/com/auth0/client/auth/RSAClientAssertionSigner.java new file mode 100644 index 000000000..657c69f72 --- /dev/null +++ b/src/main/java/com/auth0/client/auth/RSAClientAssertionSigner.java @@ -0,0 +1,102 @@ +package com.auth0.client.auth; + +import com.auth0.exception.ClientAssertionSigningException; +import com.auth0.jwt.JWT; +import com.auth0.jwt.JWTCreator; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.exceptions.JWTCreationException; +import com.auth0.utils.Asserts; +import org.jetbrains.annotations.TestOnly; + +import java.security.interfaces.RSAPrivateKey; +import java.time.Instant; +import java.util.UUID; + +/** + * An implementation of {@linkplain ClientAssertionSigner} for RSA-signed client assertions. + */ +public class RSAClientAssertionSigner implements ClientAssertionSigner { + + private final RSAPrivateKey assertionSigningKey; + private final RSASigningAlgorithm assertionSigningAlgorithm; + + + /** + * Creates a new instance. + * + * @param assertionSigningKey the private key used to sign the assertion. Must not be null. + * @param assertionSigningAlgorithm The RSA algorithm used to sign the assertion. Must not be null. + * + * @see #RSAClientAssertionSigner(RSAPrivateKey) + */ + public RSAClientAssertionSigner(RSAPrivateKey assertionSigningKey, RSASigningAlgorithm assertionSigningAlgorithm) { + Asserts.assertNotNull(assertionSigningKey, "assertion signing key"); + Asserts.assertNotNull(assertionSigningAlgorithm, "assertion signing algorithm"); + + this.assertionSigningKey = assertionSigningKey; + this.assertionSigningAlgorithm = assertionSigningAlgorithm; + } + + /** + * Creates a new instance using the RSA256 signing algorithm. + * + * @param assertionSigningKey the private key used to sign the assertion. Must not be null. + * + * @see #RSAClientAssertionSigner(RSAPrivateKey, RSASigningAlgorithm) + */ + public RSAClientAssertionSigner(RSAPrivateKey assertionSigningKey) { + this(assertionSigningKey, RSASigningAlgorithm.RSA256); + } + + @Override + public String createSignedClientAssertion(String issuer, String audience, String subject) { + Instant now = Instant.now(); + JWTCreator.Builder builder = JWT.create() + .withIssuer(issuer) + .withAudience(audience) + .withSubject(subject) + .withIssuedAt(now) + .withExpiresAt(now.plusSeconds(180)) + .withClaim("jti", UUID.randomUUID().toString()); + + switch (assertionSigningAlgorithm) { + case RSA256: + try { + return builder.sign(Algorithm.RSA256(null, assertionSigningKey)); + } catch (JWTCreationException exception) { + throw new ClientAssertionSigningException("Error creating the JWT used for client assertion using the RSA256 signing algorithm", exception); + } + case RSA384: + try { + return builder.sign(Algorithm.RSA384(null, assertionSigningKey)); + } catch (JWTCreationException exception) { + throw new ClientAssertionSigningException("Error creating the JWT used for client assertion using the RSA384 signing algorithm", exception); + } + default: + throw new ClientAssertionSigningException("Error creating the JWT used for client assertion. Unknown algorithm."); + } + } + + /** + * @return the assertion signing algorithm configured. + */ + @TestOnly + RSASigningAlgorithm getAssertionSigningAlgorithm() { + return this.assertionSigningAlgorithm; + } + + /** + * Represents the RSA algorithms available to sign the client assertion. + */ + public enum RSASigningAlgorithm { + /** + * The RSA 256 algorithm + */ + RSA256, + + /** + * The RSA 384 algorithm + */ + RSA384 + } +} diff --git a/src/main/java/com/auth0/client/mgmt/ActionsEntity.java b/src/main/java/com/auth0/client/mgmt/ActionsEntity.java index 139bbc0ef..18499058c 100644 --- a/src/main/java/com/auth0/client/mgmt/ActionsEntity.java +++ b/src/main/java/com/auth0/client/mgmt/ActionsEntity.java @@ -4,16 +4,16 @@ import com.auth0.client.mgmt.filter.BaseFilter; import com.auth0.client.mgmt.filter.PageFilter; import com.auth0.json.mgmt.actions.*; -import com.auth0.net.CustomRequest; import com.auth0.net.EmptyBodyRequest; +import com.auth0.net.BaseRequest; import com.auth0.net.Request; import com.auth0.net.VoidRequest; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.HttpMethod; +import com.auth0.net.client.HttpRequestBody; import com.auth0.utils.Asserts; import com.fasterxml.jackson.core.type.TypeReference; import okhttp3.HttpUrl; -import okhttp3.MediaType; -import okhttp3.OkHttpClient; -import okhttp3.RequestBody; /** * Class that provides an implementation of the Actions methods of the Management API as defined in https://auth0.com/docs/api/management/v2#!/Actions @@ -33,10 +33,8 @@ public class ActionsEntity extends BaseManagementEntity { private final static String EXECUTIONS_PATH = "executions"; private final static String BINDINGS_PATH = "bindings"; - private final static String AUTHORIZATION_HEADER = "Authorization"; - - ActionsEntity(OkHttpClient client, HttpUrl baseUrl, String apiToken) { - super(client, baseUrl, apiToken); + ActionsEntity(Auth0HttpClient client, HttpUrl baseUrl, TokenProvider tokenProvider) { + super(client, baseUrl, tokenProvider); } /** @@ -57,10 +55,9 @@ public Request create(Action action) { String url = builder.build().toString(); - CustomRequest request = new CustomRequest<>(client, url, "POST", new TypeReference() { + BaseRequest request = new BaseRequest<>(client, tokenProvider, url, HttpMethod.POST, new TypeReference() { }); - request.addHeader(AUTHORIZATION_HEADER, "Bearer " + apiToken); request.setBody(action); return request; } @@ -84,11 +81,8 @@ public Request get(String actionId) { .build() .toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", new TypeReference() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { }); - - request.addHeader(AUTHORIZATION_HEADER, "Bearer " + apiToken); - return request; } /** @@ -125,9 +119,7 @@ public Request delete(String actionId, boolean force) { .build() .toString(); - VoidRequest voidRequest = new VoidRequest(client, url, "DELETE"); - voidRequest.addHeader(AUTHORIZATION_HEADER, "Bearer " + apiToken); - return voidRequest; + return new VoidRequest(client, tokenProvider, url, HttpMethod.DELETE); } /** @@ -144,11 +136,8 @@ public Request getTriggers() { .build() .toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", new TypeReference() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { }); - - request.addHeader(AUTHORIZATION_HEADER, "Bearer " + apiToken); - return request; } /** @@ -173,11 +162,10 @@ public Request update(String actionId, Action action) { .build() .toString(); - CustomRequest request = new CustomRequest<>(client, url, "PATCH", new TypeReference() { + BaseRequest request = new BaseRequest<>(client, tokenProvider, url, HttpMethod.PATCH, new TypeReference() { }); request.setBody(action); - request.addHeader(AUTHORIZATION_HEADER, "Bearer " + apiToken); return request; } @@ -204,11 +192,8 @@ public Request deploy(String actionId) { .build() .toString(); - EmptyBodyRequest request = new EmptyBodyRequest<>(client, url, "POST", new TypeReference() { + return new EmptyBodyRequest<>(client, tokenProvider, url, HttpMethod.POST, new TypeReference() { }); - - request.addHeader(AUTHORIZATION_HEADER, "Bearer " + apiToken); - return request; } /** @@ -235,11 +220,8 @@ public Request getVersion(String actionId, String actionVersionId) { .build() .toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", new TypeReference() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { }); - - request.addHeader(AUTHORIZATION_HEADER, "Bearer " + apiToken); - return request; } /** @@ -269,11 +251,9 @@ public Request rollBackToVersion(String actionId, String actionVersionI .toString(); // Needed to successfully call the roll-back endpoint until DXEX-1738 is resolved. - EmptyObjectRequest request = new EmptyObjectRequest<>(client, url, "POST", new TypeReference() { - }); - request.addHeader(AUTHORIZATION_HEADER, "Bearer " + apiToken); - return request; + return new EmptyObjectRequest<>(client, tokenProvider, url, HttpMethod.POST, new TypeReference() { + }); } /** @@ -297,11 +277,8 @@ public Request getExecution(String executionId) { .build() .toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", new TypeReference() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { }); - - request.addHeader(AUTHORIZATION_HEADER, "Bearer " + apiToken); - return request; } /** @@ -321,11 +298,9 @@ public Request list(ActionsFilter filter) { applyFilter(filter, builder); String url = builder.build().toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", new TypeReference() { - }); - request.addHeader(AUTHORIZATION_HEADER, "Bearer " + apiToken); - return request; + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { + }); } /** @@ -353,11 +328,9 @@ public Request getVersions(String actionId, PageFilter filter) { applyFilter(filter, builder); String url = builder.build().toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", new TypeReference() { - }); - request.addHeader(AUTHORIZATION_HEADER, "Bearer " + apiToken); - return request; + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { + }); } /** @@ -386,11 +359,9 @@ public Request getTriggerBindings(String triggerId, PageFilter fil applyFilter(filter, builder); String url = builder.build().toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", new TypeReference() { - }); - request.addHeader(AUTHORIZATION_HEADER, "Bearer " + apiToken); - return request; + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { + }); } /** @@ -418,11 +389,10 @@ public Request updateTriggerBindings(String triggerId, BindingsUpd .build() .toString(); - CustomRequest request = new CustomRequest<>(client, url, "PATCH", new TypeReference() { + BaseRequest request = new BaseRequest<>(client, tokenProvider, url, HttpMethod.PATCH, new TypeReference() { }); request.setBody(bindingsUpdateRequest); - request.addHeader(AUTHORIZATION_HEADER, "Bearer " + apiToken); return request; } @@ -434,17 +404,13 @@ private void applyFilter(BaseFilter filter, HttpUrl.Builder builder) { // Temporary request implementation to send an empty json object on the request body. private static class EmptyObjectRequest extends EmptyBodyRequest { - EmptyObjectRequest(OkHttpClient client, String url, String method, TypeReference tType) { - super(client, url, method, tType); + EmptyObjectRequest(Auth0HttpClient client, TokenProvider tokenProvider, String url, HttpMethod method, TypeReference tType) { + super(client, tokenProvider, url, method, tType); } @Override - @SuppressWarnings("deprecation") - protected RequestBody createRequestBody() { - // Use OkHttp v3 signature to ensure binary compatibility between v3 and v4 - // https://github.com/auth0/auth0-java/issues/324 - return RequestBody.create(MediaType.parse("application/json"), "{}".getBytes()); + protected HttpRequestBody createRequestBody() { + return HttpRequestBody.create("application/json", "{}".getBytes()); } - } } diff --git a/src/main/java/com/auth0/client/mgmt/AttackProtectionEntity.java b/src/main/java/com/auth0/client/mgmt/AttackProtectionEntity.java index 3feb79430..ee96a1ad9 100644 --- a/src/main/java/com/auth0/client/mgmt/AttackProtectionEntity.java +++ b/src/main/java/com/auth0/client/mgmt/AttackProtectionEntity.java @@ -4,18 +4,19 @@ import com.auth0.json.mgmt.attackprotection.BruteForceConfiguration; import com.auth0.json.mgmt.attackprotection.SuspiciousIPThrottlingConfiguration; import com.auth0.net.Request; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.HttpMethod; import com.auth0.utils.Asserts; import com.fasterxml.jackson.core.type.TypeReference; import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; /** * Class that provides an implementation of the Attack Protection methods of the Management API as defined in * @see ManagementAPI */ public class AttackProtectionEntity extends BaseManagementEntity { - AttackProtectionEntity(OkHttpClient client, HttpUrl baseUrl, String apiToken) { - super(client, baseUrl, apiToken); + AttackProtectionEntity(Auth0HttpClient client, HttpUrl baseUrl, TokenProvider tokenProvider) { + super(client, baseUrl, tokenProvider); } /** @@ -25,7 +26,7 @@ public class AttackProtectionEntity extends BaseManagementEntity { */ public Request getBreachedPasswordSettings() { return request( - "GET", + HttpMethod.GET, new TypeReference() {}, (builder) -> builder .withPathSegments("api/v2/attack-protection/breached-password-detection") @@ -43,7 +44,7 @@ public Request updateBreachedPasswordSettings(BreachedPassword Asserts.assertNotNull(breachedPassword, "breached password"); return request( - "PATCH", + HttpMethod.PATCH, new TypeReference() {}, (builder) -> builder .withPathSegments("api/v2/attack-protection/breached-password-detection") @@ -58,7 +59,7 @@ public Request updateBreachedPasswordSettings(BreachedPassword */ public Request getBruteForceConfiguration() { return request( - "GET", + HttpMethod.GET, new TypeReference() {}, (builder) -> builder .withPathSegments("api/v2/attack-protection/brute-force-protection") @@ -75,7 +76,7 @@ public Request updateBruteForceConfiguration(BruteForce Asserts.assertNotNull(configuration, "configuration"); return request( - "PATCH", + HttpMethod.PATCH, new TypeReference() {}, (builder) -> builder .withPathSegments("api/v2/attack-protection/brute-force-protection") @@ -90,7 +91,7 @@ public Request updateBruteForceConfiguration(BruteForce */ public Request getSuspiciousIPThrottlingConfiguration() { return request( - "GET", + HttpMethod.GET, new TypeReference() {}, (builder) -> builder .withPathSegments("api/v2/attack-protection/suspicious-ip-throttling") @@ -107,7 +108,7 @@ public Request updateSuspiciousIPThrottling Asserts.assertNotNull(configuration, "configuration"); return request( - "PATCH", + HttpMethod.PATCH, new TypeReference() {}, (builder) -> builder .withPathSegments("api/v2/attack-protection/suspicious-ip-throttling") diff --git a/src/main/java/com/auth0/client/mgmt/BaseManagementEntity.java b/src/main/java/com/auth0/client/mgmt/BaseManagementEntity.java index d55df9b16..0ee987e59 100644 --- a/src/main/java/com/auth0/client/mgmt/BaseManagementEntity.java +++ b/src/main/java/com/auth0/client/mgmt/BaseManagementEntity.java @@ -1,39 +1,40 @@ package com.auth0.client.mgmt; import com.auth0.net.Request; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.HttpMethod; import com.fasterxml.jackson.core.type.TypeReference; -import java.util.function.Consumer; import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; + +import java.util.function.Consumer; abstract class BaseManagementEntity { - protected final OkHttpClient client; + protected final Auth0HttpClient client; protected final HttpUrl baseUrl; - protected final String apiToken; + protected final TokenProvider tokenProvider; - BaseManagementEntity(OkHttpClient client, HttpUrl baseUrl, String apiToken) { + BaseManagementEntity(Auth0HttpClient client, HttpUrl baseUrl, TokenProvider tokenProvider) { this.client = client; this.baseUrl = baseUrl; - this.apiToken = apiToken; + this.tokenProvider = tokenProvider; } - protected Request voidRequest(String method, Consumer> customizer) { + protected Request voidRequest(HttpMethod method, Consumer> customizer) { return customizeRequest( - new RequestBuilder<>(client, method, baseUrl, new TypeReference() { + new RequestBuilder<>(client, tokenProvider, method, baseUrl, new TypeReference() { }), customizer ); } - protected Request request(String method, TypeReference target, Consumer> customizer) { + protected Request request(HttpMethod method, TypeReference target, Consumer> customizer) { return customizeRequest( - new RequestBuilder<>(client, method, baseUrl, target), + new RequestBuilder<>(client, tokenProvider, method, baseUrl, target), customizer ); } private Request customizeRequest(RequestBuilder builder, Consumer> customizer) { - builder.withHeader("Authorization", "Bearer " + apiToken); customizer.accept(builder); return builder.build(); } diff --git a/src/main/java/com/auth0/client/mgmt/BlacklistsEntity.java b/src/main/java/com/auth0/client/mgmt/BlacklistsEntity.java index 775e19d3c..6ae2e20b6 100644 --- a/src/main/java/com/auth0/client/mgmt/BlacklistsEntity.java +++ b/src/main/java/com/auth0/client/mgmt/BlacklistsEntity.java @@ -1,13 +1,14 @@ package com.auth0.client.mgmt; -import com.auth0.json.mgmt.Token; -import com.auth0.net.CustomRequest; +import com.auth0.json.mgmt.blacklists.Token; +import com.auth0.net.BaseRequest; import com.auth0.net.Request; import com.auth0.net.VoidRequest; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.HttpMethod; import com.auth0.utils.Asserts; import com.fasterxml.jackson.core.type.TypeReference; import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; import java.util.List; @@ -21,8 +22,8 @@ @SuppressWarnings("WeakerAccess") public class BlacklistsEntity extends BaseManagementEntity { - BlacklistsEntity(OkHttpClient client, HttpUrl baseUrl, String apiToken) { - super(client, baseUrl, apiToken); + BlacklistsEntity(Auth0HttpClient client, HttpUrl baseUrl, TokenProvider tokenProvider) { + super(client, baseUrl, tokenProvider); } /** @@ -41,10 +42,8 @@ public Request> getBlacklist(String audience) { .addQueryParameter("aud", audience) .build() .toString(); - CustomRequest> request = new CustomRequest<>(client, url, "GET", new TypeReference>() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference>() { }); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; } /** @@ -62,8 +61,7 @@ public Request blacklistToken(Token token) { .addPathSegments("api/v2/blacklists/tokens") .build() .toString(); - VoidRequest request = new VoidRequest(client, url, "POST"); - request.addHeader("Authorization", "Bearer " + apiToken); + VoidRequest request = new VoidRequest(client, tokenProvider, url, HttpMethod.POST); request.setBody(token); return request; } diff --git a/src/main/java/com/auth0/client/mgmt/BrandingEntity.java b/src/main/java/com/auth0/client/mgmt/BrandingEntity.java index 11337310f..5ed229be5 100644 --- a/src/main/java/com/auth0/client/mgmt/BrandingEntity.java +++ b/src/main/java/com/auth0/client/mgmt/BrandingEntity.java @@ -4,10 +4,11 @@ import com.auth0.json.mgmt.branding.UniversalLoginTemplate; import com.auth0.json.mgmt.branding.UniversalLoginTemplateUpdate; import com.auth0.net.Request; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.HttpMethod; import com.auth0.utils.Asserts; import com.fasterxml.jackson.core.type.TypeReference; import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; /** * Class that provides an implementation of the Branding methods of the Management API as defined in https://auth0.com/docs/api/management/v2#!/Branding @@ -19,8 +20,8 @@ @SuppressWarnings("WeakerAccess") public class BrandingEntity extends BaseManagementEntity { - BrandingEntity(OkHttpClient client, HttpUrl baseUrl, String apiToken) { - super(client, baseUrl, apiToken); + BrandingEntity(Auth0HttpClient client, HttpUrl baseUrl, TokenProvider tokenProvider) { + super(client, baseUrl, tokenProvider); } /** @@ -31,7 +32,7 @@ public class BrandingEntity extends BaseManagementEntity { */ public Request getBrandingSettings() { return request( - "GET", + HttpMethod.GET, new TypeReference() { }, (builder) -> builder.withPathSegments("api/v2/branding") @@ -49,7 +50,7 @@ public Request updateBrandingSettings(BrandingSettings setting Asserts.assertNotNull(settings, "settings"); return request( - "PATCH", + HttpMethod.PATCH, new TypeReference() { }, (builder) -> builder @@ -67,7 +68,7 @@ public Request updateBrandingSettings(BrandingSettings setting */ public Request getUniversalLoginTemplate() { return request( - "GET", + HttpMethod.GET, new TypeReference() { }, (builder) -> builder.withPathSegments("api/v2/branding/templates/universal-login") @@ -82,7 +83,7 @@ public Request getUniversalLoginTemplate() { */ public Request deleteUniversalLoginTemplate() { return voidRequest( - "DELETE", + HttpMethod.DELETE, (builder) -> builder.withPathSegments("api/v2/branding/templates/universal-login") ); } @@ -97,7 +98,7 @@ public Request setUniversalLoginTemplate(UniversalLoginTemplateUpdate temp Asserts.assertNotNull(template, "template"); return voidRequest( - "PUT", + HttpMethod.PUT, (builder) -> builder .withPathSegments("api/v2/branding/templates/universal-login") .withBody(template) diff --git a/src/main/java/com/auth0/client/mgmt/ClientGrantsEntity.java b/src/main/java/com/auth0/client/mgmt/ClientGrantsEntity.java index 86943990f..99fd5f011 100644 --- a/src/main/java/com/auth0/client/mgmt/ClientGrantsEntity.java +++ b/src/main/java/com/auth0/client/mgmt/ClientGrantsEntity.java @@ -1,15 +1,18 @@ package com.auth0.client.mgmt; import com.auth0.client.mgmt.filter.ClientGrantsFilter; -import com.auth0.json.mgmt.ClientGrant; -import com.auth0.json.mgmt.ClientGrantsPage; -import com.auth0.net.CustomRequest; +import com.auth0.client.mgmt.filter.PageFilter; +import com.auth0.json.mgmt.clientgrants.ClientGrant; +import com.auth0.json.mgmt.clientgrants.ClientGrantsPage; +import com.auth0.json.mgmt.organizations.OrganizationsPage; +import com.auth0.net.BaseRequest; import com.auth0.net.Request; import com.auth0.net.VoidRequest; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.HttpMethod; import com.auth0.utils.Asserts; import com.fasterxml.jackson.core.type.TypeReference; import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; import java.util.List; import java.util.Map; @@ -24,8 +27,8 @@ @SuppressWarnings("WeakerAccess") public class ClientGrantsEntity extends BaseManagementEntity { - ClientGrantsEntity(OkHttpClient client, HttpUrl baseUrl, String apiToken) { - super(client, baseUrl, apiToken); + ClientGrantsEntity(Auth0HttpClient client, HttpUrl baseUrl, TokenProvider tokenProvider) { + super(client, baseUrl, tokenProvider); } /** @@ -46,31 +49,21 @@ public Request list(ClientGrantsFilter filter) { } String url = builder.build().toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", new TypeReference() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; } /** - * Request all the Client Grants. A token with scope read:client_grants is needed. - * See https://auth0.com/docs/api/management/v2#!/Client_Grants/get_client_grants + * Create a Client Grant. A token with scope create:client_grants is needed. + * See https://auth0.com/docs/api/management/v2#!/Client_Grants/post_client_grants * + * @param clientId the application's client id to associate this grant with. + * @param audience the audience of the grant. + * @param scope the scope to grant. * @return a Request to execute. - * @deprecated Calling this method will soon stop returning the complete list of client grants and instead, limit to the first page of results. - * Please use {@link #list(ClientGrantsFilter)} instead as it provides pagination support. */ - @Deprecated - public Request> list() { - String url = baseUrl - .newBuilder() - .addPathSegments("api/v2/client-grants") - .build() - .toString(); - CustomRequest> request = new CustomRequest<>(client, url, "GET", new TypeReference>() { - }); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; + public Request create(String clientId, String audience, String[] scope) { + return create(clientId, audience, scope, null, null); } /** @@ -80,28 +73,34 @@ public Request> list() { * @param clientId the application's client id to associate this grant with. * @param audience the audience of the grant. * @param scope the scope to grant. + * @param orgUsage Defines whether organizations can be used with client credentials exchanges for this grant. (defaults to deny when not defined) + * @param allowAnyOrg If true, any organization can be used with this grant. If disabled (default), the grant must be explicitly assigned to the desired organizations. * @return a Request to execute. */ - public Request create(String clientId, String audience, String[] scope) { + public Request create(String clientId, String audience, String[] scope, String orgUsage, Boolean allowAnyOrg) { Asserts.assertNotNull(clientId, "client id"); Asserts.assertNotNull(audience, "audience"); Asserts.assertNotNull(scope, "scope"); String url = baseUrl - .newBuilder() - .addPathSegments("api/v2/client-grants") - .build() - .toString(); - CustomRequest request = new CustomRequest<>(client, url, "POST", new TypeReference() { + .newBuilder() + .addPathSegments("api/v2/client-grants") + .build() + .toString(); + BaseRequest request = new BaseRequest<>(client, tokenProvider, url, HttpMethod.POST, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); request.addParameter("client_id", clientId); request.addParameter("audience", audience); request.addParameter("scope", scope); + if (orgUsage != null && !orgUsage.trim().isEmpty()) { + request.addParameter("organization_usage", orgUsage); + } + if (allowAnyOrg != null) { + request.addParameter("allow_any_organization", allowAnyOrg); + } return request; } - /** * Delete an existing Client Grant. A token with scope delete:client_grants is needed. * See https://auth0.com/docs/api/management/v2#!/Client_Grants/delete_client_grants_by_id @@ -118,9 +117,7 @@ public Request delete(String clientGrantId) { .addPathSegment(clientGrantId) .build() .toString(); - VoidRequest request = new VoidRequest(client, url, "DELETE"); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; + return new VoidRequest(client, tokenProvider, url, HttpMethod.DELETE); } /** @@ -132,19 +129,63 @@ public Request delete(String clientGrantId) { * @return a Request to execute. */ public Request update(String clientGrantId, String[] scope) { + return update(clientGrantId, scope, null, null); + } + + /** + * Update an existing Client Grant. A token with scope update:client_grants is needed. + * See https://auth0.com/docs/api/management/v2#!/Client_Grants/patch_client_grants_by_id + * + * @param clientGrantId the client grant id. + * @param scope the scope to grant. + * @param orgUsage Defines whether organizations can be used with client credentials exchanges for this grant. (defaults to deny when not defined) + * @param allowAnyOrg If true, any organization can be used with this grant. If disabled (default), the grant must be explicitly assigned to the desired organizations. + * @return a Request to execute. + */ + public Request update(String clientGrantId, String[] scope, String orgUsage, Boolean allowAnyOrg) { Asserts.assertNotNull(clientGrantId, "client grant id"); Asserts.assertNotNull(scope, "scope"); String url = baseUrl - .newBuilder() - .addPathSegments("api/v2/client-grants") - .addPathSegment(clientGrantId) - .build() - .toString(); - CustomRequest request = new CustomRequest<>(client, url, "PATCH", new TypeReference() { + .newBuilder() + .addPathSegments("api/v2/client-grants") + .addPathSegment(clientGrantId) + .build() + .toString(); + BaseRequest request = new BaseRequest<>(client, tokenProvider, url, HttpMethod.PATCH, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); request.addParameter("scope", scope); + if (orgUsage != null && !orgUsage.trim().isEmpty()) { + request.addParameter("organization_usage", orgUsage); + } + if (allowAnyOrg != null) { + request.addParameter("allow_any_organization", allowAnyOrg); + } return request; } + + /** + * Returns the organizations associated with this client grant. A token with scope {@code read:organization_client_grants} is required. + * @param clientGrantId the client grant ID. + * @param filter an optional filter to limit results. + * @return a request to execute. + */ + public Request listOrganizations(String clientGrantId, PageFilter filter) { + Asserts.assertNotNull(clientGrantId, "client grant ID"); + HttpUrl.Builder builder = baseUrl + .newBuilder() + .addPathSegments("api/v2/client-grants") + .addPathSegment(clientGrantId) + .addPathSegment("organizations"); + + if (filter != null) { + for (Map.Entry e : filter.getAsMap().entrySet()) { + builder.addQueryParameter(e.getKey(), String.valueOf(e.getValue())); + } + } + + String url = builder.build().toString(); + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { + }); + } } diff --git a/src/main/java/com/auth0/client/mgmt/ClientsEntity.java b/src/main/java/com/auth0/client/mgmt/ClientsEntity.java index 04d73f7bd..e44fab74c 100644 --- a/src/main/java/com/auth0/client/mgmt/ClientsEntity.java +++ b/src/main/java/com/auth0/client/mgmt/ClientsEntity.java @@ -4,14 +4,16 @@ import com.auth0.client.mgmt.filter.FieldsFilter; import com.auth0.json.mgmt.client.Client; import com.auth0.json.mgmt.client.ClientsPage; -import com.auth0.net.CustomRequest; +import com.auth0.json.mgmt.client.Credential; import com.auth0.net.EmptyBodyRequest; +import com.auth0.net.BaseRequest; import com.auth0.net.Request; import com.auth0.net.VoidRequest; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.HttpMethod; import com.auth0.utils.Asserts; import com.fasterxml.jackson.core.type.TypeReference; import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; import java.util.List; import java.util.Map; @@ -26,29 +28,8 @@ @SuppressWarnings("WeakerAccess") public class ClientsEntity extends BaseManagementEntity { - ClientsEntity(OkHttpClient client, HttpUrl baseUrl, String apiToken) { - super(client, baseUrl, apiToken); - } - - /** - * Request all the Applications. A token with scope read:clients is needed. If you also need the client_secret and encryption_key attributes the token must have read:client_keys scope. - * See https://auth0.com/docs/api/management/v2#!/Clients/get_clients - * - * @return a Request to execute. - * @deprecated Calling this method will soon stop returning the complete list of clients and instead, limit to the first page of results. - * Please use {@link #list(ClientFilter)} instead as it provides pagination support. - */ - @Deprecated - public Request> list() { - String url = baseUrl - .newBuilder() - .addPathSegments("api/v2/clients") - .build() - .toString(); - CustomRequest> request = new CustomRequest<>(client, url, "GET", new TypeReference>() { - }); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; + ClientsEntity(Auth0HttpClient client, HttpUrl baseUrl, TokenProvider tokenProvider) { + super(client, baseUrl, tokenProvider); } /** @@ -68,10 +49,8 @@ public Request list(ClientFilter filter) { } } String url = builder.build().toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", new TypeReference() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; } /** @@ -90,10 +69,8 @@ public Request get(String clientId) { .addPathSegment(clientId) .build() .toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", new TypeReference() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; } /** @@ -117,10 +94,8 @@ public Request get(String clientId, FieldsFilter filter) { } } String url = builder.build().toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", new TypeReference() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; } /** @@ -138,9 +113,8 @@ public Request create(Client client) { .addPathSegments("api/v2/clients") .build() .toString(); - CustomRequest request = new CustomRequest<>(this.client, url, "POST", new TypeReference() { + BaseRequest request = new BaseRequest<>(this.client, tokenProvider, url, HttpMethod.POST, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); request.setBody(client); return request; } @@ -161,9 +135,7 @@ public Request delete(String clientId) { .addPathSegment(clientId) .build() .toString(); - VoidRequest request = new VoidRequest(client, url, "DELETE"); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; + return new VoidRequest(client, tokenProvider, url, HttpMethod.DELETE); } /** @@ -184,9 +156,8 @@ public Request update(String clientId, Client client) { .addPathSegment(clientId) .build() .toString(); - CustomRequest request = new CustomRequest<>(this.client, url, "PATCH", new TypeReference() { + BaseRequest request = new BaseRequest<>(this.client, tokenProvider, url, HttpMethod.PATCH, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); request.setBody(client); return request; } @@ -209,9 +180,117 @@ public Request rotateSecret(String clientId) { .addPathSegment("rotate-secret") .build() .toString(); - CustomRequest request = new EmptyBodyRequest<>(this.client, url, "POST", new TypeReference() { + return new EmptyBodyRequest<>(this.client, tokenProvider, url, HttpMethod.POST, new TypeReference() { + }); + } + + /** + * Creates an Application's client credential. A token with scope {@code create:client_credentials} is required. + * + * @param clientId the application's client id. + * @param credential the credential to create. + * @return a Request to execute. + */ + public Request createCredential(String clientId, Credential credential) { + Asserts.assertNotNull(clientId, "client id"); + + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/clients") + .addPathSegment(clientId) + .addPathSegment("credentials") + .build() + .toString(); + BaseRequest request = new BaseRequest<>(this.client, tokenProvider, url, HttpMethod.POST, new TypeReference() { + }); + request.setBody(credential); + return request; + } + + /** + * Get the client credentials associated with this application. A token with scope {@code read:client_credentials} is required. + * @param clientId the ID of the application + * @return a request to execute. + */ + public Request> listCredentials(String clientId) { + Asserts.assertNotNull(clientId, "client id"); + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/clients") + .addPathSegment(clientId) + .addPathSegment("credentials").build().toString(); + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference>() { + }); + } + + /** + * Get a client credentials object. A token with scope {@code read:client_credentials} is required. + * @param clientId the ID of the application. + * @param credentialId the ID of the credential to retrieve. + * @return a request to execute. + */ + public Request getCredential(String clientId, String credentialId) { + Asserts.assertNotNull(clientId, "client id"); + Asserts.assertNotNull(credentialId, "credential id"); + + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/clients") + .addPathSegment(clientId) + .addPathSegment("credentials") + .addPathSegment(credentialId) + .build().toString(); + + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { + }); + } + + /** + * Deletes a client credential. A token with scope {@code } is required. + * @param clientId the ID of the application. + * @param credentialId the ID of the credential to delete + * @return a request to execute. + */ + public Request deleteCredential(String clientId, String credentialId) { + Asserts.assertNotNull(clientId, "client id"); + Asserts.assertNotNull(credentialId, "credential id"); + + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/clients") + .addPathSegment(clientId) + .addPathSegment("credentials") + .addPathSegment(credentialId) + .build() + .toString(); + return new VoidRequest(client, tokenProvider, url, HttpMethod.DELETE); + } + + /** + * Update an existing client credential. A token with scope update:client_credentials is needed. + * See https://auth0.com/docs/api/management/v2/clients/patch-credentials-by-credential-id + * + * @param clientId the application's client id. + * @param credentialId the ID of the credential. + * @param credential the credential to update. + * @return a Request to execute. + */ + public Request updateCredential(String clientId, String credentialId, Credential credential) { + Asserts.assertNotNull(clientId, "client id"); + Asserts.assertNotNull(credentialId, "credential id"); + Asserts.assertNotNull(credential, "credential"); + + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/clients") + .addPathSegment(clientId) + .addPathSegment("credentials") + .addPathSegment(credentialId) + .build() + .toString(); + BaseRequest request = new BaseRequest<>(this.client, tokenProvider, url, HttpMethod.PATCH, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); + request.setBody(credential); return request; } } diff --git a/src/main/java/com/auth0/client/mgmt/ConnectionsEntity.java b/src/main/java/com/auth0/client/mgmt/ConnectionsEntity.java index 8ed6bbbd3..8e8a1b7c9 100644 --- a/src/main/java/com/auth0/client/mgmt/ConnectionsEntity.java +++ b/src/main/java/com/auth0/client/mgmt/ConnectionsEntity.java @@ -1,15 +1,17 @@ package com.auth0.client.mgmt; import com.auth0.client.mgmt.filter.ConnectionFilter; -import com.auth0.json.mgmt.Connection; -import com.auth0.json.mgmt.ConnectionsPage; -import com.auth0.net.CustomRequest; +import com.auth0.client.mgmt.filter.EnabledClientsFilter; +import com.auth0.json.mgmt.connections.*; +import com.auth0.net.BaseRequest; +import com.auth0.net.EmptyBodyRequest; import com.auth0.net.Request; import com.auth0.net.VoidRequest; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.HttpMethod; import com.auth0.utils.Asserts; import com.fasterxml.jackson.core.type.TypeReference; import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; import java.util.List; import java.util.Map; @@ -24,8 +26,8 @@ @SuppressWarnings("WeakerAccess") public class ConnectionsEntity extends BaseManagementEntity { - ConnectionsEntity(OkHttpClient client, HttpUrl baseUrl, String apiToken) { - super(client, baseUrl, apiToken); + ConnectionsEntity(Auth0HttpClient client, HttpUrl baseUrl, TokenProvider tokenProvider) { + super(client, baseUrl, tokenProvider); } @@ -46,42 +48,11 @@ public Request listAll(ConnectionFilter filter) { } } String url = builder.build().toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", new TypeReference() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; } - /** - * Request all the ConnectionsEntity. A token with scope read:connections is needed. - * See https://auth0.com/docs/api/management/v2#!/Connections/get_connections - * - * @param filter the filter to use. Can be null. - * @return a Request to execute. - * @deprecated Calling this method will soon stop returning the complete list of connections and instead, limit to the first page of results. - * Please use {@link #listAll(ConnectionFilter)} instead as it provides pagination support. - */ - @Deprecated - public Request> list(ConnectionFilter filter) { - HttpUrl.Builder builder = baseUrl - .newBuilder() - .addPathSegments("api/v2/connections"); - if (filter != null) { - for (Map.Entry e : filter.getAsMap().entrySet()) { - //This check below is to prevent JSON parsing errors - if (!e.getKey().equalsIgnoreCase("include_totals")) { - builder.addQueryParameter(e.getKey(), String.valueOf(e.getValue())); - } - } - } - String url = builder.build().toString(); - CustomRequest> request = new CustomRequest<>(client, url, "GET", new TypeReference>() { - }); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; - } - /** * Request a Connection. A token with scope read:connections is needed. * See https://auth0.com/docs/api/management/v2#!/Connections/get_connections_by_id @@ -103,10 +74,8 @@ public Request get(String connectionId, ConnectionFilter filter) { } } String url = builder.build().toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", new TypeReference() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; } /** @@ -124,9 +93,8 @@ public Request create(Connection connection) { .addPathSegments("api/v2/connections") .build() .toString(); - CustomRequest request = new CustomRequest<>(this.client, url, "POST", new TypeReference() { + BaseRequest request = new BaseRequest<>(this.client, tokenProvider, url, HttpMethod.POST, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); request.setBody(connection); return request; } @@ -147,9 +115,7 @@ public Request delete(String connectionId) { .addPathSegment(connectionId) .build() .toString(); - VoidRequest request = new VoidRequest(client, url, "DELETE"); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; + return new VoidRequest(client, tokenProvider, url, HttpMethod.DELETE); } /** @@ -170,9 +136,8 @@ public Request update(String connectionId, Connection connection) { .addPathSegment(connectionId) .build() .toString(); - CustomRequest request = new CustomRequest<>(this.client, url, "PATCH", new TypeReference() { + BaseRequest request = new BaseRequest<>(this.client, tokenProvider, url, HttpMethod.PATCH, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); request.setBody(connection); return request; } @@ -197,8 +162,305 @@ public Request deleteUser(String connectionId, String email) { .addQueryParameter("email", email) .build() .toString(); - VoidRequest request = new VoidRequest(this.client, url, "DELETE"); - request.addHeader("Authorization", "Bearer " + apiToken); + return new VoidRequest(this.client, tokenProvider, url, HttpMethod.DELETE); + } + + /** + * Get the Connections Scim Configuration. + * A token with scope read:scim_config is needed. + * @see https://auth0.com/docs/api/management/v2#!/connections/get-scim-configuration + * @param connectionId the connection id. + * @return a Request to execute. + */ + public Request getScimConfiguration( String connectionId) { + Asserts.assertNotNull(connectionId, "connection id"); + + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/connections") + .addPathSegment(connectionId) + .addPathSegment("scim-configuration") + .build() + .toString(); + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { + }); + } + + /** + * Delete the Connections Scim Configuration. + * A token with scope delete:scim_config is needed. + * @see https://auth0.com/docs/api/management/v2#!/connections/delete-scim-configuration + * @param connectionId the connection id. + * @return a Request to execute. + */ + public Request deleteScimConfiguration(String connectionId) { + Asserts.assertNotNull(connectionId, "connection id"); + + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/connections") + .addPathSegment(connectionId) + .addPathSegment("scim-configuration") + .build() + .toString(); + return new VoidRequest(client, tokenProvider, url, HttpMethod.DELETE); + } + + /** + * Update the Connections Scim Configuration. + * A token with scope update:scim_config is needed. + * @see https://auth0.com/docs/api/management/v2#!/connections/patch-scim-configuration + * @param connectionId the connection id. + * @param scimConfigurationRequest the scim configuration request. + * @return a Request to execute. + */ + public Request updateScimConfiguration(String connectionId, ScimConfigurationRequest scimConfigurationRequest){ + Asserts.assertNotNull(connectionId, "connection id"); + Asserts.assertNotNull(scimConfigurationRequest, "scim configuration request"); + Asserts.assertNotNull(scimConfigurationRequest.getUserIdAttribute(), "user id attribute"); + Asserts.assertNotNull(scimConfigurationRequest.getMapping(), "mapping"); + + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/connections") + .addPathSegment(connectionId) + .addPathSegment("scim-configuration") + .build() + .toString(); + + BaseRequest request = new BaseRequest<>(client, tokenProvider, url, HttpMethod.PATCH, new TypeReference() { + }); + request.setBody(scimConfigurationRequest); return request; } + + /** + * Create the Connections Scim Configuration. + * A token with scope create:scim_config is needed. + * @see https://auth0.com/docs/api/management/v2#!/connections/post-scim-configuration + * @param connectionId the connection id. + * @param request the scim configuration request. + * @return a Request to execute. + */ + public Request createScimConfiguration(String connectionId, ScimConfigurationRequest request){ + Asserts.assertNotNull(connectionId, "connection id"); + + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/connections") + .addPathSegment(connectionId) + .addPathSegment("scim-configuration") + .build() + .toString(); + + BaseRequest baseRequest = new BaseRequest<>(client, tokenProvider, url, HttpMethod.POST, new TypeReference() { + }); + baseRequest.setBody(request); + return baseRequest; + } + + /** + * Get the Scim Configuration default mapping by its connection Id. + * A token with scope read:scim_config is needed. + * @see https://auth0.com/docs/api/management/v2#!/connections/get-default-mapping + * @param connectionId the connection id. + * @return a Request to execute. + */ + public Request getDefaultScimConfiguration(String connectionId){ + Asserts.assertNotNull(connectionId, "connection id"); + + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/connections") + .addPathSegment(connectionId) + .addPathSegment("scim-configuration") + .addPathSegment("default-mapping") + .build() + .toString(); + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { + }); + } + + /** + * Get the Connections Scim Tokens. + * A token with scope read:scim_token is needed. + * @see https://auth0.com/docs/api/management/v2#!/connections/get-scim-tokens + * @param connectionId the connection id. + * @return a Request to execute. + */ + public Request> getScimToken(String connectionId){ + Asserts.assertNotNull(connectionId, "connection id"); + + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/connections") + .addPathSegment(connectionId) + .addPathSegments("scim-configuration/tokens") + .build() + .toString(); + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference>() { + }); + } + + /** + * Create a Connections Scim Token. + * A token with scope create:scim_token is needed. + * @see https://auth0.com/docs/api/management/v2#!/connections/post-scim-token + * @param connectionId the connection id. + * @param scimTokenRequest the scim token request. + * @return a Request to execute. + */ + public Request createScimToken(String connectionId, ScimTokenRequest scimTokenRequest){ + Asserts.assertNotNull(connectionId, "connection id"); + Asserts.assertNotNull(scimTokenRequest, "scim token request"); + + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/connections") + .addPathSegment(connectionId) + .addPathSegments("scim-configuration/tokens") + .build() + .toString(); + + BaseRequest request = new BaseRequest<>(client, tokenProvider, url, HttpMethod.POST, new TypeReference() { + }); + request.setBody(scimTokenRequest); + return request; + } + + /** + * Delete a Connections Scim Token. + * A token with scope delete:scim_token is needed. + * @see https://auth0.com/docs/api/management/v2#!/connections/delete-tokens-by-token-id + * @param connectionId the connection id. + * @param tokenId the token id. + * @return a Request to execute. + */ + public Request deleteScimToken(String connectionId, String tokenId){ + Asserts.assertNotNull(connectionId, "connection id"); + Asserts.assertNotNull(tokenId, "token id"); + + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/connections") + .addPathSegment(connectionId) + .addPathSegments("scim-configuration/tokens") + .addPathSegment(tokenId) + .build() + .toString(); + + return new VoidRequest(client, tokenProvider, url, HttpMethod.DELETE); + } + + /** + * Check the Connection Status. + * A token with scope read:connections is needed. + * @see https://auth0.com/docs/api/management/v2#!/connections/get-status + * @param connectionId the connection id. + * @return a Request to execute. + */ + public Request checkConnectionStatus(String connectionId){ + Asserts.assertNotNull(connectionId, "connection id"); + + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/connections") + .addPathSegment(connectionId) + .addPathSegments("status") + .build() + .toString(); + + return new VoidRequest(client, tokenProvider, url, HttpMethod.GET); + } + + /** + * Get the enabled clients for a connection. + * A token with scope read:connections is needed. + * @see https://auth0.com/docs/api/management/v2#!/connections/get-connection-clients + * @param filter the filter to use. Can be null. + * @return a Request to execute. + */ + public Request getEnabledClients(String connectionId, EnabledClientsFilter filter) { + Asserts.assertNotNull(connectionId, "connection id"); + + HttpUrl.Builder builder = baseUrl + .newBuilder() + .addPathSegments("api/v2/connections") + .addPathSegment(connectionId) + .addPathSegment("clients"); + + if (filter != null) { + for (Map.Entry e : filter.getAsMap().entrySet()) { + builder.addQueryParameter(e.getKey(), String.valueOf(e.getValue())); + } + } + String url = builder.build().toString(); + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { + }); + } + + /** + * Update the enabled clients for a connection. + * A token with scope update:connections is needed. + * @see https://auth0.com/docs/api/management/v2#!/connections/patch-clients + * + * @param connectionId the connection id. + * @param enabledClientRequests the enabled client request to set. + * @return a Request to execute. + */ + public Request updateEnabledClients(String connectionId, List enabledClientRequests){ + Asserts.assertNotNull(connectionId, "connection id"); + Asserts.assertNotEmpty(enabledClientRequests, "enabled client Request"); + + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/connections") + .addPathSegment(connectionId) + .addPathSegments("clients") + .build() + .toString(); + + VoidRequest request = new VoidRequest(client, tokenProvider, url, HttpMethod.PATCH); + request.setBody(enabledClientRequests); + return request; + } + + /** + * Get the Connection Keys. + * A token with scope read:connections_keys is needed. + * @param connectionId the connection id. + * @return a Request to execute. + */ + public Request> getKeys(String connectionId) { + Asserts.assertNotNull(connectionId, "connection id"); + + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/connections") + .addPathSegment(connectionId) + .addPathSegment("keys") + .build() + .toString(); + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference>() { + }); + } + + /** * Rotate the Connection Keys. + * A token with scope create:connections_keys and update:connections_keys is needed. + * @param connectionId the connection id. + * @return a Request to execute. + */ + public Request rotateKey(String connectionId) { + Asserts.assertNotNull(connectionId, "connection id"); + + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/connections") + .addPathSegment(connectionId) + .addPathSegments("keys/rotate") + .build() + .toString(); + + return new EmptyBodyRequest<>(client, tokenProvider, url, HttpMethod.POST, new TypeReference() {}); + } } diff --git a/src/main/java/com/auth0/client/mgmt/DeviceCredentialsEntity.java b/src/main/java/com/auth0/client/mgmt/DeviceCredentialsEntity.java index 8f0e7d451..f235c586b 100644 --- a/src/main/java/com/auth0/client/mgmt/DeviceCredentialsEntity.java +++ b/src/main/java/com/auth0/client/mgmt/DeviceCredentialsEntity.java @@ -1,14 +1,15 @@ package com.auth0.client.mgmt; import com.auth0.client.mgmt.filter.DeviceCredentialsFilter; -import com.auth0.json.mgmt.DeviceCredentials; -import com.auth0.net.CustomRequest; +import com.auth0.json.mgmt.devicecredentials.DeviceCredentials; +import com.auth0.net.BaseRequest; import com.auth0.net.Request; import com.auth0.net.VoidRequest; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.HttpMethod; import com.auth0.utils.Asserts; import com.fasterxml.jackson.core.type.TypeReference; import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; import java.util.List; import java.util.Map; @@ -23,8 +24,8 @@ @SuppressWarnings("WeakerAccess") public class DeviceCredentialsEntity extends BaseManagementEntity { - DeviceCredentialsEntity(OkHttpClient client, HttpUrl baseUrl, String apiToken) { - super(client, baseUrl, apiToken); + DeviceCredentialsEntity(Auth0HttpClient client, HttpUrl baseUrl, TokenProvider tokenProvider) { + super(client, baseUrl, tokenProvider); } /** @@ -44,10 +45,8 @@ public Request> list(DeviceCredentialsFilter filter) { } } String url = builder.build().toString(); - CustomRequest> request = new CustomRequest<>(client, url, "GET", new TypeReference>() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference>() { }); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; } /** @@ -65,9 +64,8 @@ public Request create(DeviceCredentials deviceCredentials) { .addPathSegments("api/v2/device-credentials") .build() .toString(); - CustomRequest request = new CustomRequest<>(this.client, url, "POST", new TypeReference() { + BaseRequest request = new BaseRequest<>(this.client, tokenProvider, url, HttpMethod.POST, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); request.setBody(deviceCredentials); return request; } @@ -88,8 +86,6 @@ public Request delete(String deviceCredentialsId) { .addPathSegment(deviceCredentialsId) .build() .toString(); - VoidRequest request = new VoidRequest(client, url, "DELETE"); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; + return new VoidRequest(client, tokenProvider, url, HttpMethod.DELETE); } } diff --git a/src/main/java/com/auth0/client/mgmt/EmailProviderEntity.java b/src/main/java/com/auth0/client/mgmt/EmailProviderEntity.java index 074594c57..b221d410e 100644 --- a/src/main/java/com/auth0/client/mgmt/EmailProviderEntity.java +++ b/src/main/java/com/auth0/client/mgmt/EmailProviderEntity.java @@ -2,13 +2,14 @@ import com.auth0.client.mgmt.filter.FieldsFilter; import com.auth0.json.mgmt.emailproviders.EmailProvider; -import com.auth0.net.CustomRequest; +import com.auth0.net.BaseRequest; import com.auth0.net.Request; import com.auth0.net.VoidRequest; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.HttpMethod; import com.auth0.utils.Asserts; import com.fasterxml.jackson.core.type.TypeReference; import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; import java.util.Map; @@ -21,8 +22,8 @@ */ @SuppressWarnings("WeakerAccess") public class EmailProviderEntity extends BaseManagementEntity { - EmailProviderEntity(OkHttpClient client, HttpUrl baseUrl, String apiToken) { - super(client, baseUrl, apiToken); + EmailProviderEntity(Auth0HttpClient client, HttpUrl baseUrl, TokenProvider tokenProvider) { + super(client, baseUrl, tokenProvider); } /** @@ -42,10 +43,8 @@ public Request get(FieldsFilter filter) { } } String url = builder.build().toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", new TypeReference() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; } /** @@ -63,9 +62,8 @@ public Request setup(EmailProvider emailProvider) { .addPathSegments("api/v2/emails/provider") .build() .toString(); - CustomRequest request = new CustomRequest<>(this.client, url, "POST", new TypeReference() { + BaseRequest request = new BaseRequest<>(this.client, tokenProvider, url, HttpMethod.POST, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); request.setBody(emailProvider); return request; } @@ -82,9 +80,7 @@ public Request delete() { .addPathSegments("api/v2/emails/provider") .build() .toString(); - VoidRequest request = new VoidRequest(client, url, "DELETE"); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; + return new VoidRequest(client, tokenProvider, url, HttpMethod.DELETE); } /** @@ -102,9 +98,8 @@ public Request update(EmailProvider emailProvider) { .addPathSegments("api/v2/emails/provider") .build() .toString(); - CustomRequest request = new CustomRequest<>(this.client, url, "PATCH", new TypeReference() { + BaseRequest request = new BaseRequest<>(this.client, tokenProvider, url, HttpMethod.PATCH, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); request.setBody(emailProvider); return request; } diff --git a/src/main/java/com/auth0/client/mgmt/EmailTemplatesEntity.java b/src/main/java/com/auth0/client/mgmt/EmailTemplatesEntity.java index 93a4af645..6ab3943db 100644 --- a/src/main/java/com/auth0/client/mgmt/EmailTemplatesEntity.java +++ b/src/main/java/com/auth0/client/mgmt/EmailTemplatesEntity.java @@ -1,12 +1,13 @@ package com.auth0.client.mgmt; -import com.auth0.json.mgmt.EmailTemplate; -import com.auth0.net.CustomRequest; +import com.auth0.json.mgmt.emailtemplates.EmailTemplate; +import com.auth0.net.BaseRequest; import com.auth0.net.Request; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.HttpMethod; import com.auth0.utils.Asserts; import com.fasterxml.jackson.core.type.TypeReference; import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; /** * Class that provides an implementation of the Email Templates methods of the Management API as defined in https://auth0.com/docs/api/management/v2#!/Email_Templates @@ -27,9 +28,12 @@ public class EmailTemplatesEntity extends BaseManagementEntity { public static final String TEMPLATE_CHANGE_PASSWORD = "change_password"; public static final String TEMPLATE_PASSWORD_RESET = "password_reset"; public static final String TEMPLATE_MFA_OOB_CODE = "mfa_oob_code"; + public static final String TEMPLATE_VERIFY_EMAIL_BY_CODE = "verify_email_by_code"; + public static final String TEMPLATE_RESET_EMAIL_BY_CODE = "reset_email_by_code"; + public static final String TEMPLATE_USER_INVITATION = "user_invitation"; - EmailTemplatesEntity(OkHttpClient client, HttpUrl baseUrl, String apiToken) { - super(client, baseUrl, apiToken); + EmailTemplatesEntity(Auth0HttpClient client, HttpUrl baseUrl, TokenProvider tokenProvider) { + super(client, baseUrl, tokenProvider); } /** @@ -46,10 +50,8 @@ public Request get(String templateName) { .addPathSegments("api/v2/email-templates") .addPathSegment(templateName); String url = builder.build().toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", new TypeReference() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; } /** @@ -67,9 +69,8 @@ public Request create(EmailTemplate template) { .addPathSegments("api/v2/email-templates") .build() .toString(); - CustomRequest request = new CustomRequest<>(this.client, url, "POST", new TypeReference() { + BaseRequest request = new BaseRequest<>(this.client, tokenProvider, url, HttpMethod.POST, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); request.setBody(template); return request; } @@ -92,9 +93,8 @@ public Request update(String templateName, EmailTemplate template .addPathSegment(templateName) .build() .toString(); - CustomRequest request = new CustomRequest<>(this.client, url, "PATCH", new TypeReference() { + BaseRequest request = new BaseRequest<>(this.client, tokenProvider, url, HttpMethod.PATCH, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); request.setBody(template); return request; } diff --git a/src/main/java/com/auth0/client/mgmt/GrantsEntity.java b/src/main/java/com/auth0/client/mgmt/GrantsEntity.java index fd44f20a3..5e0b6c45c 100644 --- a/src/main/java/com/auth0/client/mgmt/GrantsEntity.java +++ b/src/main/java/com/auth0/client/mgmt/GrantsEntity.java @@ -1,15 +1,16 @@ package com.auth0.client.mgmt; import com.auth0.client.mgmt.filter.GrantsFilter; -import com.auth0.json.mgmt.Grant; -import com.auth0.json.mgmt.GrantsPage; -import com.auth0.net.CustomRequest; +import com.auth0.json.mgmt.grants.Grant; +import com.auth0.json.mgmt.grants.GrantsPage; +import com.auth0.net.BaseRequest; import com.auth0.net.Request; import com.auth0.net.VoidRequest; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.HttpMethod; import com.auth0.utils.Asserts; import com.fasterxml.jackson.core.type.TypeReference; import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; import java.util.List; import java.util.Map; @@ -24,8 +25,8 @@ @SuppressWarnings("WeakerAccess") public class GrantsEntity extends BaseManagementEntity { - GrantsEntity(OkHttpClient client, HttpUrl baseUrl, String apiToken) { - super(client, baseUrl, apiToken); + GrantsEntity(Auth0HttpClient client, HttpUrl baseUrl, TokenProvider tokenProvider) { + super(client, baseUrl, tokenProvider); } /** @@ -50,35 +51,8 @@ public Request list(String userId, GrantsFilter filter) { } String url = builder.build().toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", new TypeReference() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; - } - - /** - * Request all Grants. A token with scope read:grants is needed - * See https://auth0.com/docs/api/management/v2#!/Grants/get_grants - * - * @param userId The user id of the grants to retrieve - * @return a Request to execute. - * @deprecated Calling this method will soon stop returning the complete list of grants and instead, limit to the first page of results. - * Please use {@link #list(String, GrantsFilter)} instead as it provides pagination support. - */ - @Deprecated - public Request> list(String userId) { - Asserts.assertNotNull(userId, "user id"); - - String url = baseUrl - .newBuilder() - .addPathSegments("api/v2/grants") - .addQueryParameter("user_id", userId) - .build() - .toString(); - CustomRequest> request = new CustomRequest<>(client, url, "GET", new TypeReference>() { - }); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; } /** @@ -97,9 +71,7 @@ public Request delete(String grantId) { .addPathSegment(grantId) .build() .toString(); - VoidRequest request = new VoidRequest(client, url, "DELETE"); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; + return new VoidRequest(client, tokenProvider, url, HttpMethod.DELETE); } /** @@ -118,9 +90,7 @@ public Request deleteAll(String userId) { .addQueryParameter("user_id", userId) .build() .toString(); - VoidRequest request = new VoidRequest(client, url, "DELETE"); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; + return new VoidRequest(client, tokenProvider, url, HttpMethod.DELETE); } } diff --git a/src/main/java/com/auth0/client/mgmt/GuardianEntity.java b/src/main/java/com/auth0/client/mgmt/GuardianEntity.java index 965ce7ade..18474bb5c 100644 --- a/src/main/java/com/auth0/client/mgmt/GuardianEntity.java +++ b/src/main/java/com/auth0/client/mgmt/GuardianEntity.java @@ -1,12 +1,12 @@ package com.auth0.client.mgmt; import com.auth0.json.mgmt.guardian.*; -import com.auth0.net.CustomRequest; import com.auth0.net.Request; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.HttpMethod; import com.auth0.utils.Asserts; import com.fasterxml.jackson.core.type.TypeReference; import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; import java.util.List; @@ -20,8 +20,8 @@ @SuppressWarnings("WeakerAccess") public class GuardianEntity extends BaseManagementEntity { - GuardianEntity(OkHttpClient client, HttpUrl baseUrl, String apiToken) { - super(client, baseUrl, apiToken); + GuardianEntity(Auth0HttpClient client, HttpUrl baseUrl, TokenProvider tokenProvider) { + super(client, baseUrl, tokenProvider); } /** @@ -35,7 +35,7 @@ public Request createEnrollmentTicket(EnrollmentTicket enrollm Asserts.assertNotNull(enrollmentTicket, "enrollment ticket"); return request( - "POST", + HttpMethod.POST, new TypeReference() { }, (builder) -> builder @@ -55,7 +55,7 @@ public Request deleteEnrollment(String enrollmentId) { Asserts.assertNotNull(enrollmentId, "enrollment id"); return voidRequest( - "DELETE", + HttpMethod.DELETE, (builder) -> builder.withPathSegments("api/v2/guardian/enrollments").withPathSegments(enrollmentId) ); } @@ -69,7 +69,7 @@ public Request deleteEnrollment(String enrollmentId) { */ public Request getTemplates() { return request( - "GET", + HttpMethod.GET, new TypeReference() { }, (builder) -> builder.withPathSegments("api/v2/guardian/factors/sms/templates") @@ -88,7 +88,7 @@ public Request updateTemplates(GuardianTemplates guardianTemp Asserts.assertNotNull(guardianTemplates, "guardian templates"); return request( - "PUT", + HttpMethod.PUT, new TypeReference() { }, (builder) -> builder @@ -105,7 +105,7 @@ public Request updateTemplates(GuardianTemplates guardianTemp */ public Request> listFactors() { return request( - "GET", + HttpMethod.GET, new TypeReference>() { }, (builder) -> builder.withPathSegments("api/v2/guardian/factors") @@ -125,7 +125,7 @@ public Request updateFactor(String name, Boolean enabled) { Asserts.assertNotNull(enabled, "enabled"); return request( - "PUT", + HttpMethod.PUT, new TypeReference() { }, (builder) -> builder @@ -142,7 +142,7 @@ public Request updateFactor(String name, Boolean enabled) { */ public Request getTwilioFactorProvider() { return request( - "GET", + HttpMethod.GET, new TypeReference() { }, (builder) -> builder.withPathSegments("api/v2/guardian/factors/sms/providers/twilio") @@ -160,7 +160,7 @@ public Request updateTwilioFactorProvider(TwilioFactorProv Asserts.assertNotNull(provider, "provider"); return request( - "PUT", + HttpMethod.PUT, new TypeReference() { }, (builder) -> builder @@ -188,7 +188,7 @@ public Request resetTwilioFactorProvider() { */ public Request getSNSFactorProvider() { return request( - "GET", + HttpMethod.GET, new TypeReference() { }, (builder) -> builder.withPathSegments("api/v2/guardian/factors/push-notification/providers/sns") @@ -206,7 +206,7 @@ public Request updateSNSFactorProvider(SNSFactorProvider prov Asserts.assertNotNull(provider, "provider"); return request( - "PUT", + HttpMethod.PUT, new TypeReference() { }, (builder) -> builder @@ -234,7 +234,7 @@ public Request resetSNSFactorProvider() { */ public Request> getAuthenticationPolicies() { return request( - "GET", + HttpMethod.GET, new TypeReference>() { }, (builder) -> builder.withPathSegments("api/v2/guardian/policies") @@ -252,7 +252,7 @@ public Request> updateAuthenticationPolicies(List policies) Asserts.assertNotNull(policies, "policies"); return request( - "PUT", + HttpMethod.PUT, new TypeReference>() { }, (builder) -> builder diff --git a/src/main/java/com/auth0/client/mgmt/JobsEntity.java b/src/main/java/com/auth0/client/mgmt/JobsEntity.java index de81c828d..7de6ed373 100644 --- a/src/main/java/com/auth0/client/mgmt/JobsEntity.java +++ b/src/main/java/com/auth0/client/mgmt/JobsEntity.java @@ -2,24 +2,25 @@ import com.auth0.client.mgmt.filter.UsersExportFilter; import com.auth0.client.mgmt.filter.UsersImportOptions; -import com.auth0.json.mgmt.EmailVerificationIdentity; +import com.auth0.json.mgmt.tickets.EmailVerificationIdentity; import com.auth0.json.mgmt.jobs.Job; import com.auth0.json.mgmt.jobs.JobErrorDetails; -import com.auth0.net.CustomRequest; +import com.auth0.net.BaseRequest; import com.auth0.net.MultipartRequest; import com.auth0.net.Request; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.Auth0HttpResponse; +import com.auth0.net.client.HttpMethod; import com.auth0.utils.Asserts; import com.fasterxml.jackson.core.type.TypeReference; -import java.io.IOException; -import java.util.Collections; -import java.util.List; import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; import java.io.File; +import java.io.IOException; +import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; -import okhttp3.ResponseBody; /** * Class that provides an implementation of the Jobs methods of the Management API as defined in https://auth0.com/docs/api/management/v2#!/Jobs @@ -31,13 +32,13 @@ @SuppressWarnings("WeakerAccess") public class JobsEntity extends BaseManagementEntity { - JobsEntity(OkHttpClient client, HttpUrl baseUrl, String apiToken) { - super(client, baseUrl, apiToken); + JobsEntity(Auth0HttpClient client, HttpUrl baseUrl, TokenProvider tokenProvider) { + super(client, baseUrl, tokenProvider); } /** * Request a Job. A token with scope create:users is needed. - * See https://auth0.com/docs/api/management/v2#!/Jobs/get_jobs_by_id. + * See GET Jobs by ID. * * @param jobId the id of the job to retrieve. * @return a Request to execute. @@ -52,15 +53,13 @@ public Request get(String jobId) { .build() .toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", new TypeReference() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; } /** * Get error details of a failed job. A token with scope create:users is needed. - * See https://auth0.com/docs/api/management/v2#!/Jobs/get_errors. + * See GET Job Errors. * * @param jobId the id of the job to retrieve. * @return a Request to execute. @@ -78,22 +77,20 @@ public Request> getErrorDetails(String jobId) { TypeReference> jobErrorDetailsListType = new TypeReference>() { }; - CustomRequest> request = new CustomRequest>(client, url, "GET", jobErrorDetailsListType) { + return new BaseRequest>(client, tokenProvider, url, HttpMethod.GET, jobErrorDetailsListType) { @Override - protected List readResponseBody(ResponseBody body) throws IOException { - if (body.contentLength() == 0) { + protected List readResponseBody(Auth0HttpResponse response) throws IOException { + if (response.getBody() == null || response.getBody().length() == 0) { return Collections.emptyList(); } - return super.readResponseBody(body); + return super.readResponseBody(response); } }; - request.addHeader("Authorization", "Bearer " + apiToken); - return request; } /** * Sends an Email Verification. A token with scope update:users is needed. - * See https://auth0.com/docs/api/management/v2#!/Jobs/post_verification_email. + * See POST Verification Email. * * @param userId The user_id of the user to whom the email will be sent. * @param clientId The id of the client, if not provided the global one will be used. @@ -108,7 +105,7 @@ public Request sendVerificationEmail(String userId, String clientId) { /** * Sends an Email Verification. A token with scope update:users is needed. - * See https://auth0.com/docs/api/management/v2#!/Jobs/post_verification_email. + * See POST Verification Email. * * @param userId The user_id of the user to whom the email will be sent. * @param clientId The id of the client, if not provided the global one will be used. @@ -124,7 +121,7 @@ public Request sendVerificationEmail(String userId, String clientId, EmailV /** * Sends an Email Verification. A token with scope update:users is needed. - * See https://auth0.com/docs/api/management/v2#!/Jobs/post_verification_email. + * See POST Verification Email. * * @param userId The user_id of the user to whom the email will be sent. * @param clientId The id of the client, if not provided the global one will be used. @@ -157,22 +154,24 @@ public Request sendVerificationEmail(String userId, String clientId, EmailV Asserts.assertNotNull(emailVerificationIdentity.getUserId(), "identity user id"); requestBody.put("identity", emailVerificationIdentity); } - CustomRequest request = new CustomRequest<>(client, url, "POST", new TypeReference() { + BaseRequest request = new BaseRequest<>(client, tokenProvider, url, HttpMethod.POST, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); request.setBody(requestBody); return request; } /** + * @deprecated Use {@link #exportUsers(UsersExportFilter)} instead. + * * Requests a Users Exports job. A token with scope read:users is needed. - * See https://auth0.com/docs/api/management/v2#!/Jobs/post_users_exports. - * See https://auth0.com/docs/users/guides/bulk-user-exports. + * See POST Users Exports. + * See Bulk User Exports. * * @param connectionId The id of the connection to export the users from. * @param filter the filter to use. Can be null. * @return a Request to execute. */ + @Deprecated public Request exportUsers(String connectionId, UsersExportFilter filter) { Asserts.assertNotNull(connectionId, "connection id"); @@ -188,17 +187,42 @@ public Request exportUsers(String connectionId, UsersExportFilter filter) { requestBody.putAll(filter.getAsMap()); } - CustomRequest request = new CustomRequest<>(client, url, "POST", new TypeReference() { + BaseRequest request = new BaseRequest<>(client, tokenProvider, url, HttpMethod.POST, new TypeReference() { + }); + request.setBody(requestBody); + return request; + } + + /** + * Requests a Users Exports job. A token with scope read:users is needed. + * See POST Users Exports. + * See Bulk User Exports. + * + * @param filter the filter to use. Can be null. + * @return a Request to execute. + */ + public Request exportUsers(UsersExportFilter filter) { + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/jobs/users-exports") + .build() + .toString(); + + Map requestBody = new HashMap<>(); + if (filter != null) { + requestBody.putAll(filter.getAsMap()); + } + + BaseRequest request = new BaseRequest<>(client, tokenProvider, url, HttpMethod.POST, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); request.setBody(requestBody); return request; } /** * Requests a Users Imports job. A token with scope write:users is needed. - * See https://auth0.com/docs/api/management/v2#!/Jobs/post_users_imports. - * See https://auth0.com/docs/users/guides/bulk-user-imports. + * See POST User Imports. + * See Bulk User Imports. * * @param connectionId The id of the connection to import the users to. * @param users The users file. Must have an array with the users' information in JSON format. @@ -214,7 +238,8 @@ public Request importUsers(String connectionId, File users, UsersImportOpti .addPathSegments("api/v2/jobs/users-imports") .build() .toString(); - MultipartRequest request = new MultipartRequest<>(client, url, "POST", new TypeReference() { + + MultipartRequest request = new MultipartRequest<>(client, tokenProvider, url, HttpMethod.POST, new TypeReference() { }); if (options != null) { for (Map.Entry e : options.getAsMap().entrySet()) { @@ -223,7 +248,6 @@ public Request importUsers(String connectionId, File users, UsersImportOpti } request.addPart("connection_id", connectionId); request.addPart("users", users, "text/json"); - request.addHeader("Authorization", "Bearer " + apiToken); return request; } } diff --git a/src/main/java/com/auth0/client/mgmt/KeysEntity.java b/src/main/java/com/auth0/client/mgmt/KeysEntity.java index ea66193b7..65c7db8f5 100644 --- a/src/main/java/com/auth0/client/mgmt/KeysEntity.java +++ b/src/main/java/com/auth0/client/mgmt/KeysEntity.java @@ -1,15 +1,22 @@ package com.auth0.client.mgmt; -import com.auth0.json.mgmt.Key; -import com.auth0.net.CustomRequest; +import com.auth0.client.mgmt.filter.EncryptionKeyFilter; +import com.auth0.json.mgmt.keys.EncryptionKey; +import com.auth0.json.mgmt.keys.EncryptionKeysPage; +import com.auth0.json.mgmt.keys.EncryptionWrappingKeyResponse; +import com.auth0.json.mgmt.keys.Key; import com.auth0.net.EmptyBodyRequest; +import com.auth0.net.BaseRequest; +import com.auth0.net.EmptyBodyVoidRequest; import com.auth0.net.Request; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.HttpMethod; import com.auth0.utils.Asserts; import com.fasterxml.jackson.core.type.TypeReference; import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; import java.util.List; +import java.util.Map; /** * Class that provides an implementation of the Keys methods of the Management API as defined in https://auth0.com/docs/api/management/v2#!/Keys @@ -20,9 +27,9 @@ */ public class KeysEntity extends BaseManagementEntity { - KeysEntity(OkHttpClient client, HttpUrl baseUrl, - String apiToken) { - super(client, baseUrl, apiToken); + KeysEntity(Auth0HttpClient client, HttpUrl baseUrl, + TokenProvider tokenProvider) { + super(client, baseUrl, tokenProvider); } /** @@ -37,10 +44,8 @@ public Request> list() { .newBuilder() .addEncodedPathSegments("api/v2/keys/signing"); String url = builder.build().toString(); - CustomRequest> request = new CustomRequest<>(this.client, url, "GET", new TypeReference>() { + return new BaseRequest<>(this.client, tokenProvider, url, HttpMethod.GET, new TypeReference>() { }); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; } @@ -59,10 +64,8 @@ public Request get(String kid) { .addPathSegments("api/v2/keys/signing") .addPathSegment(kid); String url = builder.build().toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", new TypeReference() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; } /** @@ -78,10 +81,8 @@ public Request rotate() { .addPathSegments("api/v2/keys/signing/rotate") .build() .toString(); - CustomRequest request = new EmptyBodyRequest<>(this.client, url, "POST", new TypeReference() { + return new EmptyBodyRequest<>(this.client, tokenProvider, url, HttpMethod.POST, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; } /** @@ -102,9 +103,160 @@ public Request revoke(String kid) { .addPathSegment("revoke") .build() .toString(); - CustomRequest request = new EmptyBodyRequest<>(this.client, url, "PUT", new TypeReference() { + return new EmptyBodyRequest<>(this.client, tokenProvider, url, HttpMethod.PUT, new TypeReference() { + }); + } + + /** + * Perform rekeying operation on the key hierarchy. + * A token with scope create:encryption_keys and update:encryption_keys is needed + * See https://auth0.com/docs/api/management/v2#!/Keys/post-encryption-rekey + * @return a Request to execute. + */ + public Request postEncryptionRekey(){ + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/keys/encryption/rekey") + .build() + .toString(); + + return new EmptyBodyVoidRequest<>(this.client, tokenProvider, url, HttpMethod.POST, new TypeReference() {}); + } + + /** + * Get all encryption keys. + * A token with scope read:encryption_keys is needed + * See https://auth0.com/docs/api/management/v2#!/Keys/get-encryption-keys + * @param filter Filter to apply. Use null to get all encryption keys. + * @return a Request to execute. + */ + public Request listEncryptionKeys(EncryptionKeyFilter filter){ + + HttpUrl.Builder builder = baseUrl + .newBuilder() + .addPathSegments("api/v2/keys/encryption"); + + if (filter != null) { + for (Map.Entry e : filter.getAsMap().entrySet()) { + builder.addQueryParameter(e.getKey(), String.valueOf(e.getValue())); + } + } + + String url = builder.build().toString(); + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { + }); + } + + /** + * Get the encryption key with the given kid. + * A token with scope read:encryption_keys is needed + * See https://auth0.com/docs/api/management/v2#!/Keys/get-encryption-key + * @param kid Encryption key ID + * @return A Request to execute + */ + public Request getEncryptionKey(String kid){ + Asserts.assertNotNull(kid, "kid"); + + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/keys/encryption") + .addPathSegment(kid) + .build() + .toString(); + + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { + }); + } + + /** + * Create a new encryption key. + * A token with scope create:encryption_keys is needed + * See https://auth0.com/docs/api/management/v2#!/Keys/post-encryption + * @param type key type + * @return a Request to execute. + */ + public Request createEncryptionKey(String type) { + Asserts.assertNotNull(type, "type"); + + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/keys/encryption") + .build() + .toString(); + + BaseRequest request = new BaseRequest<>(client, tokenProvider, url, HttpMethod.POST, new TypeReference() { + }); + + request.addParameter("type", type); + return request; + } + + /** + * Import an encryption key. + * A token with scope update:encryption_keys is needed + * See https://auth0.com/docs/api/management/v2#!/Keys/post-encryption-key + * @param wrappedKey Base64 encoded ciphertext of key material wrapped by public wrapping key. + * @param kid Encryption key ID + * @return A Request to execute + */ + public Request importEncryptionKey(String wrappedKey, String kid) { + Asserts.assertNotNull(wrappedKey, "wrappedKey"); + Asserts.assertNotNull(kid, "kid"); + + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/keys/encryption") + .addPathSegment(kid) + .build() + .toString(); + + BaseRequest request = new BaseRequest<>(client, tokenProvider, url, HttpMethod.POST, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); + + request.addParameter("wrapped_key", wrappedKey); return request; } + + /** + * Delete the encryption key with the given kid. + * A token with scope delete:encryption_keys is needed + * See https://auth0.com/docs/api/management/v2#!/delete-encryption-key + * @param kid Encryption key ID + * @return a Request to execute. + */ + public Request deleteEncryptionKey(String kid) { + Asserts.assertNotNull(kid, "kid"); + + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/keys/encryption") + .addPathSegment(kid) + .build() + .toString(); + + return new EmptyBodyVoidRequest<>(client, tokenProvider, url, HttpMethod.DELETE, new TypeReference() { + }); + } + + /** + * Create a new encryption wrapping key. + * A token with scope create:encryption_keys is needed + * See https://auth0.com/docs/api/management/v2#!/Keys/post-encryption-wrapping-key + * @param kid Encryption key ID + * @return a Request to execute. + */ + public Request createEncryptionWrappingKey(String kid) { + Asserts.assertNotNull(kid, "kid"); + + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/keys/encryption") + .addPathSegment(kid) + .addPathSegment("wrapping-key") + .build() + .toString(); + + return new EmptyBodyRequest<>(client, tokenProvider, url, HttpMethod.POST, new TypeReference() { + }); + } } diff --git a/src/main/java/com/auth0/client/mgmt/LogEventsEntity.java b/src/main/java/com/auth0/client/mgmt/LogEventsEntity.java index 1c1e569dc..bf58361b1 100644 --- a/src/main/java/com/auth0/client/mgmt/LogEventsEntity.java +++ b/src/main/java/com/auth0/client/mgmt/LogEventsEntity.java @@ -3,12 +3,13 @@ import com.auth0.client.mgmt.filter.LogEventFilter; import com.auth0.json.mgmt.logevents.LogEvent; import com.auth0.json.mgmt.logevents.LogEventsPage; -import com.auth0.net.CustomRequest; +import com.auth0.net.BaseRequest; import com.auth0.net.Request; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.HttpMethod; import com.auth0.utils.Asserts; import com.fasterxml.jackson.core.type.TypeReference; import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; import java.util.Map; @@ -24,8 +25,8 @@ @SuppressWarnings("WeakerAccess") public class LogEventsEntity extends BaseManagementEntity { - LogEventsEntity(OkHttpClient client, HttpUrl baseUrl, String apiToken) { - super(client, baseUrl, apiToken); + LogEventsEntity(Auth0HttpClient client, HttpUrl baseUrl, TokenProvider tokenProvider) { + super(client, baseUrl, tokenProvider); } /** @@ -49,10 +50,8 @@ public Request list(LogEventFilter filter) { } } String url = builder.build().toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", new TypeReference() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; } /** @@ -71,9 +70,7 @@ public Request get(String logEventId) { .addPathSegment(logEventId) .build() .toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", new TypeReference() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; } } diff --git a/src/main/java/com/auth0/client/mgmt/LogStreamsEntity.java b/src/main/java/com/auth0/client/mgmt/LogStreamsEntity.java index febb49c5f..2bc444148 100644 --- a/src/main/java/com/auth0/client/mgmt/LogStreamsEntity.java +++ b/src/main/java/com/auth0/client/mgmt/LogStreamsEntity.java @@ -1,13 +1,14 @@ package com.auth0.client.mgmt; import com.auth0.json.mgmt.logstreams.LogStream; -import com.auth0.net.CustomRequest; +import com.auth0.net.BaseRequest; import com.auth0.net.Request; import com.auth0.net.VoidRequest; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.HttpMethod; import com.auth0.utils.Asserts; import com.fasterxml.jackson.core.type.TypeReference; import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; import java.util.List; @@ -21,10 +22,9 @@ public class LogStreamsEntity extends BaseManagementEntity { private final static String LOG_STREAMS_PATH = "api/v2/log-streams"; - private final static String AUTHORIZATION_HEADER = "Authorization"; - LogStreamsEntity(OkHttpClient client, HttpUrl baseUrl, String apiToken) { - super(client, baseUrl, apiToken); + LogStreamsEntity(Auth0HttpClient client, HttpUrl baseUrl, TokenProvider tokenProvider) { + super(client, baseUrl, tokenProvider); } /** @@ -40,10 +40,8 @@ public Request> list() { .build() .toString(); - CustomRequest> request = new CustomRequest<>(client, url, "GET", new TypeReference>() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference>() { }); - request.addHeader(AUTHORIZATION_HEADER, "Bearer " + apiToken); - return request; } /** @@ -63,10 +61,8 @@ public Request get(String logStreamId) { .build() .toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", new TypeReference() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { }); - request.addHeader(AUTHORIZATION_HEADER, "Bearer " + apiToken); - return request; } /** @@ -85,8 +81,7 @@ public Request create(LogStream logStream) { .build() .toString(); - CustomRequest request = new CustomRequest<>(client, url, "POST", new TypeReference(){}); - request.addHeader(AUTHORIZATION_HEADER, "Bearer " + apiToken); + BaseRequest request = new BaseRequest<>(client, tokenProvider, url, HttpMethod.POST, new TypeReference(){}); request.setBody(logStream); return request; } @@ -110,9 +105,8 @@ public Request update(String logStreamId, LogStream logStream) { .build() .toString(); - CustomRequest request = new CustomRequest<>(client, url, "PATCH", new TypeReference(){ + BaseRequest request = new BaseRequest<>(client, tokenProvider, url, HttpMethod.PATCH, new TypeReference(){ }); - request.addHeader(AUTHORIZATION_HEADER, "Bearer " + apiToken); request.setBody(logStream); return request; } @@ -134,8 +128,6 @@ public Request delete(String logStreamId) { .build() .toString(); - VoidRequest request = new VoidRequest(client, url, "DELETE"); - request.addHeader(AUTHORIZATION_HEADER, "Bearer " + apiToken); - return request; + return new VoidRequest(client, tokenProvider, url, HttpMethod.DELETE); } } diff --git a/src/main/java/com/auth0/client/mgmt/ManagementAPI.java b/src/main/java/com/auth0/client/mgmt/ManagementAPI.java index 9a8bf3e47..5105aee65 100644 --- a/src/main/java/com/auth0/client/mgmt/ManagementAPI.java +++ b/src/main/java/com/auth0/client/mgmt/ManagementAPI.java @@ -1,18 +1,11 @@ package com.auth0.client.mgmt; -import com.auth0.client.HttpOptions; -import com.auth0.client.LoggingOptions; -import com.auth0.client.ProxyOptions; -import com.auth0.net.RateLimitInterceptor; -import com.auth0.net.Telemetry; -import com.auth0.net.TelemetryInterceptor; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.DefaultHttpClient; import com.auth0.utils.Asserts; -import okhttp3.*; -import okhttp3.logging.HttpLoggingInterceptor; -import okhttp3.logging.HttpLoggingInterceptor.Level; - -import java.io.IOException; -import java.util.concurrent.TimeUnit; +import okhttp3.HttpUrl; +import okhttp3.OkHttpClient; +import org.jetbrains.annotations.TestOnly; /** * Class that provides an implementation of the Management API methods defined in https://auth0.com/docs/api/management/v2. @@ -26,35 +19,26 @@ public class ManagementAPI { private final HttpUrl baseUrl; - private String apiToken; - private final OkHttpClient client; - private final TelemetryInterceptor telemetry; - private final HttpLoggingInterceptor logging; + private TokenProvider tokenProvider; + private final Auth0HttpClient client; /** * Create an instance with the given tenant's domain and API token. - * In addition, accepts an {@link HttpOptions} that will be used to configure the networking client. + * In addition, accepts an {@link com.auth0.client.HttpOptions} that will be used to configure the networking client. * See the Management API section in the readme or visit https://auth0.com/docs/api/management/v2/tokens * to learn how to obtain a token. * + * @deprecated Use the {@link Builder} to configure and create instances. + * * @param domain the tenant's domain. * @param apiToken the token to authenticate the calls with. * @param options configuration options for this client instance. * @see #ManagementAPI(String, String) */ - public ManagementAPI(String domain, String apiToken, HttpOptions options) { - Asserts.assertNotNull(domain, "domain"); - Asserts.assertNotNull(apiToken, "api token"); - - this.baseUrl = createBaseUrl(domain); - if (baseUrl == null) { - throw new IllegalArgumentException("The domain had an invalid format and couldn't be parsed as an URL."); - } - this.apiToken = apiToken; - - telemetry = new TelemetryInterceptor(); - logging = new HttpLoggingInterceptor(); - client = buildNetworkingClient(options); + @Deprecated + @SuppressWarnings("baz") + public ManagementAPI(String domain, String apiToken, com.auth0.client.HttpOptions options) { + this(domain, SimpleTokenProvider.create(apiToken), buildNetworkingClient(options)); } /** @@ -62,127 +46,86 @@ public ManagementAPI(String domain, String apiToken, HttpOptions options) { * See the Management API section in the readme or visit https://auth0.com/docs/api/management/v2/tokens * to learn how to obtain a token. * + * @deprecated Use the {@link Builder} to configure and create instances. + * * @param domain the tenant's domain. * @param apiToken the token to authenticate the calls with. */ + @Deprecated public ManagementAPI(String domain, String apiToken) { - this(domain, apiToken, new HttpOptions()); + this(domain, SimpleTokenProvider.create(apiToken), DefaultHttpClient.newBuilder().build()); } /** - * Given a set of options, it creates a new instance of the {@link OkHttpClient} - * configuring them according to their availability. + * Instantiate a new {@link Builder} to configure and build a new ManagementAPI client. * - * @param options the options to set to the client. - * @return a new networking client instance configured as requested. + * @param domain the tenant's domain. Must be a non-null valid HTTPS domain. + * @param apiToken the token to use when making API requests to the Auth0 Management API. + * @return a Builder for further configuration. */ - private OkHttpClient buildNetworkingClient(HttpOptions options) { - OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder(); - final ProxyOptions proxyOptions = options.getProxyOptions(); - if (proxyOptions != null) { - //Set proxy - clientBuilder.proxy(proxyOptions.getProxy()); - //Set authentication, if present - final String proxyAuth = proxyOptions.getBasicAuthentication(); - if (proxyAuth != null) { - clientBuilder.proxyAuthenticator(new Authenticator() { - - private static final String PROXY_AUTHORIZATION_HEADER = "Proxy-Authorization"; - - @Override - public okhttp3.Request authenticate(Route route, Response response) throws IOException { - if (response.request().header(PROXY_AUTHORIZATION_HEADER) != null) { - return null; - } - return response.request().newBuilder() - .header(PROXY_AUTHORIZATION_HEADER, proxyAuth) - .build(); - } - }); - } - } - configureLogging(options.getLoggingOptions()); - Dispatcher dispatcher = new Dispatcher(); - dispatcher.setMaxRequestsPerHost(options.getMaxRequestsPerHost()); - dispatcher.setMaxRequests(options.getMaxRequests()); - return clientBuilder - .addInterceptor(logging) - .addInterceptor(telemetry) - .addInterceptor(new RateLimitInterceptor(options.getManagementAPIMaxRetries())) - .connectTimeout(options.getConnectTimeout(), TimeUnit.SECONDS) - .readTimeout(options.getReadTimeout(), TimeUnit.SECONDS) - .dispatcher(dispatcher) - .build(); + public static ManagementAPI.Builder newBuilder(String domain, String apiToken) { + return new ManagementAPI.Builder(domain, apiToken); } /** - * Update the API token to use on new calls. This is useful when the token is about to expire or already has. - * Please note you'll need to obtain the corresponding entity again for this to apply. e.g. call {@link #clients()} again. - * See the Management API section in the readme or visit https://auth0.com/docs/api/management/v2/tokens to learn how to obtain a token. + * Instantiate a new {@link Builder} to configure and build a new ManagementAPI client. * - * @param apiToken the token to authenticate the calls with. + * @param domain the tenant's domain. Must be a non-null valid HTTPS domain. + * @param tokenProvider the API Token provider to use when making requests. + * @return a Builder for further configuration. */ - public void setApiToken(String apiToken) { - Asserts.assertNotNull(apiToken, "api token"); - this.apiToken = apiToken; + public static ManagementAPI.Builder newBuilder(String domain, TokenProvider tokenProvider) { + return new ManagementAPI.Builder(domain, tokenProvider); } - /** - * Avoid sending Telemetry data in every request to the Auth0 servers. - */ - public void doNotSendTelemetry() { - telemetry.setEnabled(false); + private ManagementAPI(String domain, TokenProvider tokenProvider, Auth0HttpClient httpClient) { + Asserts.assertNotNull(domain, "domain"); + Asserts.assertNotNull(tokenProvider, "token provider"); + + this.baseUrl = createBaseUrl(domain); + if (baseUrl == null) { + throw new IllegalArgumentException("The domain had an invalid format and couldn't be parsed as an URL."); + } + this.tokenProvider = tokenProvider; + this.client = httpClient; } /** - * Setter for the Telemetry to send in every request to Auth0. + * Given a set of options, it creates a new instance of the {@link OkHttpClient} + * configuring them according to their availability. * - * @param telemetry to send in every request to Auth0 + * @param options the options to set to the client. + * @return a new networking client instance configured as requested. */ - public void setTelemetry(Telemetry telemetry) { - this.telemetry.setTelemetry(telemetry); + @SuppressWarnings("deprecation") + private static DefaultHttpClient buildNetworkingClient(com.auth0.client.HttpOptions options) { + Asserts.assertNotNull(options, "Http options"); + return DefaultHttpClient.newBuilder() + .withLogging(options.getLoggingOptions()) + .withMaxRetries(options.getManagementAPIMaxRetries()) + .withMaxRequests(options.getMaxRequests()) + .withMaxRequestsPerHost(options.getMaxRequestsPerHost()) + .withProxy(options.getProxyOptions()) + .withConnectTimeout(options.getConnectTimeout()) + .withReadTimeout(options.getReadTimeout()) + .build(); } /** - * @deprecated use the logging configuration available in {@link HttpOptions#setLoggingOptions(LoggingOptions)} - * - * Whether to enable or not the current HTTP Logger for every request and response line, body, and headers. - * Warning: Enabling logging can leek sensitive information, and should only be done in a controlled, non-production environment. + * Update the API token to use on new calls. This is useful when the token is about to expire or already has. + * Please note you'll need to obtain the corresponding entity again for this to apply. e.g. call {@link #clients()} again. + * See the Management API section in the readme or visit https://auth0.com/docs/api/management/v2/tokens to learn how to obtain a token. * - * @param enabled whether to enable the HTTP logger or not. + * @param apiToken the token to authenticate the calls with. */ - @Deprecated - public void setLoggingEnabled(boolean enabled) { - logging.setLevel(enabled ? Level.BODY : Level.NONE); - } - - private void configureLogging(LoggingOptions loggingOptions) { - if (loggingOptions == null) { - logging.setLevel(Level.NONE); - return; - } - switch (loggingOptions.getLogLevel()) { - case BASIC: - logging.setLevel(Level.BASIC); - break; - case HEADERS: - logging.setLevel(Level.HEADERS); - break; - case BODY: - logging.setLevel(Level.BODY); - break; - case NONE: - default: - logging.setLevel(Level.NONE); - } - for (String header : loggingOptions.getHeadersToRedact()) { - logging.redactHeader(header); - } + public void setApiToken(String apiToken) { + Asserts.assertNotNull(apiToken, "api token"); + this.tokenProvider = SimpleTokenProvider.create(apiToken); } - //Visible for testing - OkHttpClient getClient() { - return client; + @TestOnly + Auth0HttpClient getHttpClient() { + return this.client; } //Visible for testing @@ -204,7 +147,7 @@ private HttpUrl createBaseUrl(String domain) { * @return the Branding entity. */ public BrandingEntity branding() { - return new BrandingEntity(client, baseUrl, apiToken); + return new BrandingEntity(client, baseUrl, tokenProvider); } /** @@ -213,7 +156,7 @@ public BrandingEntity branding() { * @return the Client Grants entity. */ public ClientGrantsEntity clientGrants() { - return new ClientGrantsEntity(client, baseUrl, apiToken); + return new ClientGrantsEntity(client, baseUrl, tokenProvider); } /** @@ -222,7 +165,7 @@ public ClientGrantsEntity clientGrants() { * @return the Applications entity. */ public ClientsEntity clients() { - return new ClientsEntity(client, baseUrl, apiToken); + return new ClientsEntity(client, baseUrl, tokenProvider); } /** @@ -231,7 +174,7 @@ public ClientsEntity clients() { * @return the Connections entity. */ public ConnectionsEntity connections() { - return new ConnectionsEntity(client, baseUrl, apiToken); + return new ConnectionsEntity(client, baseUrl, tokenProvider); } /** @@ -240,7 +183,7 @@ public ConnectionsEntity connections() { * @return the Device Credentials entity. */ public DeviceCredentialsEntity deviceCredentials() { - return new DeviceCredentialsEntity(client, baseUrl, apiToken); + return new DeviceCredentialsEntity(client, baseUrl, tokenProvider); } /** @@ -249,7 +192,7 @@ public DeviceCredentialsEntity deviceCredentials() { * @return the Grants entity. */ public GrantsEntity grants() { - return new GrantsEntity(client, baseUrl, apiToken); + return new GrantsEntity(client, baseUrl, tokenProvider); } /** @@ -258,7 +201,7 @@ public GrantsEntity grants() { * @return the Log Events entity. */ public LogEventsEntity logEvents() { - return new LogEventsEntity(client, baseUrl, apiToken); + return new LogEventsEntity(client, baseUrl, tokenProvider); } /** @@ -267,7 +210,7 @@ public LogEventsEntity logEvents() { * @return the Log Streams entity. */ public LogStreamsEntity logStreams() { - return new LogStreamsEntity(client, baseUrl, apiToken); + return new LogStreamsEntity(client, baseUrl, tokenProvider); } /** @@ -276,7 +219,7 @@ public LogStreamsEntity logStreams() { * @return the Rules entity. */ public RulesEntity rules() { - return new RulesEntity(client, baseUrl, apiToken); + return new RulesEntity(client, baseUrl, tokenProvider); } /** @@ -285,7 +228,7 @@ public RulesEntity rules() { * @return the Rules Configs entity. */ public RulesConfigsEntity rulesConfigs() { - return new RulesConfigsEntity(client, baseUrl, apiToken); + return new RulesConfigsEntity(client, baseUrl, tokenProvider); } /** @@ -294,7 +237,7 @@ public RulesConfigsEntity rulesConfigs() { * @return the User Blocks entity. */ public UserBlocksEntity userBlocks() { - return new UserBlocksEntity(client, baseUrl, apiToken); + return new UserBlocksEntity(client, baseUrl, tokenProvider); } /** @@ -303,7 +246,7 @@ public UserBlocksEntity userBlocks() { * @return the Users entity. */ public UsersEntity users() { - return new UsersEntity(client, baseUrl, apiToken); + return new UsersEntity(client, baseUrl, tokenProvider); } /** @@ -312,7 +255,7 @@ public UsersEntity users() { * @return the Blacklists entity. */ public BlacklistsEntity blacklists() { - return new BlacklistsEntity(client, baseUrl, apiToken); + return new BlacklistsEntity(client, baseUrl, tokenProvider); } /** @@ -321,7 +264,7 @@ public BlacklistsEntity blacklists() { * @return the Email Templates entity. */ public EmailTemplatesEntity emailTemplates() { - return new EmailTemplatesEntity(client, baseUrl, apiToken); + return new EmailTemplatesEntity(client, baseUrl, tokenProvider); } /** @@ -330,7 +273,7 @@ public EmailTemplatesEntity emailTemplates() { * @return the Email Provider entity. */ public EmailProviderEntity emailProvider() { - return new EmailProviderEntity(client, baseUrl, apiToken); + return new EmailProviderEntity(client, baseUrl, tokenProvider); } /** @@ -339,7 +282,7 @@ public EmailProviderEntity emailProvider() { * @return the Guardian entity. */ public GuardianEntity guardian() { - return new GuardianEntity(client, baseUrl, apiToken); + return new GuardianEntity(client, baseUrl, tokenProvider); } /** @@ -348,7 +291,7 @@ public GuardianEntity guardian() { * @return the Stats entity. */ public StatsEntity stats() { - return new StatsEntity(client, baseUrl, apiToken); + return new StatsEntity(client, baseUrl, tokenProvider); } /** @@ -357,7 +300,7 @@ public StatsEntity stats() { * @return the Tenants entity. */ public TenantsEntity tenants() { - return new TenantsEntity(client, baseUrl, apiToken); + return new TenantsEntity(client, baseUrl, tokenProvider); } /** @@ -366,7 +309,7 @@ public TenantsEntity tenants() { * @return the Tickets entity. */ public TicketsEntity tickets() { - return new TicketsEntity(client, baseUrl, apiToken); + return new TicketsEntity(client, baseUrl, tokenProvider); } /** @@ -375,7 +318,7 @@ public TicketsEntity tickets() { * @return the Resource Servers entity. */ public ResourceServerEntity resourceServers() { - return new ResourceServerEntity(client, baseUrl, apiToken); + return new ResourceServerEntity(client, baseUrl, tokenProvider); } /** @@ -384,7 +327,7 @@ public ResourceServerEntity resourceServers() { * @return the Jobs entity. */ public JobsEntity jobs() { - return new JobsEntity(client, baseUrl, apiToken); + return new JobsEntity(client, baseUrl, tokenProvider); } /** @@ -393,7 +336,7 @@ public JobsEntity jobs() { * @return the Roles entity. */ public RolesEntity roles() { - return new RolesEntity(client, baseUrl, apiToken); + return new RolesEntity(client, baseUrl, tokenProvider); } /** @@ -402,7 +345,7 @@ public RolesEntity roles() { * @return the Organizations entity. */ public OrganizationsEntity organizations() { - return new OrganizationsEntity(client, baseUrl, apiToken); + return new OrganizationsEntity(client, baseUrl, tokenProvider); } /** @@ -411,7 +354,7 @@ public OrganizationsEntity organizations() { * @return the Actions entity. */ public ActionsEntity actions() { - return new ActionsEntity(client, baseUrl, apiToken); + return new ActionsEntity(client, baseUrl, tokenProvider); } /** @@ -420,7 +363,7 @@ public ActionsEntity actions() { * @return the Attack Protection Entity */ public AttackProtectionEntity attackProtection() { - return new AttackProtectionEntity(client, baseUrl, apiToken); + return new AttackProtectionEntity(client, baseUrl, tokenProvider); } /** @@ -429,6 +372,101 @@ public AttackProtectionEntity attackProtection() { * @return the Keys Entity */ public KeysEntity keys() { - return new KeysEntity(client, baseUrl, apiToken); + return new KeysEntity(client, baseUrl, tokenProvider); + } + + /** + * Getter for the RefreshTokens Entity + * @return the RefreshTokens Entity + */ + public RefreshTokensEntity refreshTokens() { + return new RefreshTokensEntity(client, baseUrl, tokenProvider); + } + + /** + * Getter for the Sessions Entity + * @return the Sessions Entity + */ + public SessionsEntity sessions() { + return new SessionsEntity(client, baseUrl, tokenProvider); + } + + /** + * Getter for the Prompts Entity + * @return the Prompts Entity + */ + public PromptsEntity prompts() { + return new PromptsEntity(client, baseUrl, tokenProvider); + } + + /** + * Getter for the SelfServiceProfiles Entity + * @return the SelfServiceProfiles Entity + */ + public SelfServiceProfilesEntity selfServiceProfiles() { + return new SelfServiceProfilesEntity(client, baseUrl, tokenProvider); + } + + /** + * Getter for the Network Acls Entity + * @return the Network Acls Entity + */ + public NetworkAclsEntity networkAcls() { + return new NetworkAclsEntity(client, baseUrl, tokenProvider); + } + + /** + * Getter for the User Attribute Profiles Entity + * @return the User Attribute Profiles Entity + */ + public UserAttributeProfilesEntity userAttributeProfiles() { + return new UserAttributeProfilesEntity(client, baseUrl, tokenProvider); + } + + /** + * Builder for {@link ManagementAPI} API client instances. + */ + public static class Builder { + private final String domain; + private final TokenProvider tokenProvider; + private Auth0HttpClient httpClient = DefaultHttpClient.newBuilder().build(); + + /** + * Create a new Builder + * @param domain the domain of the tenant. + * @param apiToken the API token used to make requests to the Auth0 Management API. + */ + public Builder(String domain, String apiToken) { + this(domain, SimpleTokenProvider.create(apiToken)); + } + + /** + * Create a new Builder + * @param domain the domain of the tenant. + * @param tokenProvider the API Token provider to use when making requests. + */ + public Builder(String domain, TokenProvider tokenProvider) { + this.domain = domain; + this.tokenProvider = tokenProvider; + } + + /** + * Configure the client with an {@link Auth0HttpClient}. + * @param httpClient the HTTP client to use when making requests. + * @return the builder instance. + * @see DefaultHttpClient + */ + public Builder withHttpClient(Auth0HttpClient httpClient) { + this.httpClient = httpClient; + return this; + } + + /** + * Build a {@link ManagementAPI} instance using this builder's configuration. + * @return the configured {@code ManagementAPI} instance. + */ + public ManagementAPI build() { + return new ManagementAPI(domain, tokenProvider, httpClient); + } } } diff --git a/src/main/java/com/auth0/client/mgmt/NetworkAclsEntity.java b/src/main/java/com/auth0/client/mgmt/NetworkAclsEntity.java new file mode 100644 index 000000000..d0d8818c3 --- /dev/null +++ b/src/main/java/com/auth0/client/mgmt/NetworkAclsEntity.java @@ -0,0 +1,152 @@ +package com.auth0.client.mgmt; + +import com.auth0.client.mgmt.filter.NetworkAclsFilter; +import com.auth0.json.mgmt.networkacls.NetworkAcls; +import com.auth0.json.mgmt.networkacls.NetworkAclsPage; +import com.auth0.net.BaseRequest; +import com.auth0.net.Request; +import com.auth0.net.VoidRequest; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.HttpMethod; +import com.auth0.utils.Asserts; +import com.fasterxml.jackson.core.type.TypeReference; +import okhttp3.HttpUrl; + +import java.util.Map; + +public class NetworkAclsEntity extends BaseManagementEntity { + + private final static String ORGS_PATH = "api/v2/network-acls"; + + NetworkAclsEntity(Auth0HttpClient client, HttpUrl baseUrl, TokenProvider tokenProvider) { + super(client, baseUrl, tokenProvider); + } + + /** + * Lists all Network ACLs for the Auth0 tenant. + * This method allows you to filter the results using the provided {@link NetworkAclsFilter}. + * A token with scope read:network_acls is needed. + * + * @see https://auth0.com/docs/api/management/v2#!/network-acls/get-network-acls + * @param filter the filter to apply to the request, can be null. + * @return a Request that can be executed to retrieve a page of Network ACLs. + */ + public Request list(NetworkAclsFilter filter) { + HttpUrl.Builder builder = baseUrl.newBuilder() + .addPathSegments(ORGS_PATH); + + if (filter != null) { + for (Map.Entry e : filter.getAsMap().entrySet()) { + builder.addQueryParameter(e.getKey(), String.valueOf(e.getValue())); + } + } + + String url = builder.build().toString(); + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference(){ + }); + } + + /** + * Creates a new Network ACL for the Auth0 tenant. + * A token with scope create:network_acls is needed. + * + * @see https://auth0.com/docs/api/management/v2#!/network-acls/post-network-acls + * @param networkAcls the Network ACL to create. + * @return a Request that can be executed to create the Network ACL. + */ + public Request create(NetworkAcls networkAcls) { + Asserts.assertNotNull(networkAcls, "network acls"); + String url = baseUrl.newBuilder() + .addPathSegments(ORGS_PATH) + .build().toString(); + BaseRequest request = new BaseRequest<>(client, tokenProvider, url, HttpMethod.POST, new TypeReference(){}); + request.setBody(networkAcls); + return request; + } + + /** + * Get a Network ACL by its ID. + * A token with scope read:network_acls is needed. + * + * @see https://auth0.com/docs/api/management/v2#!/network-acls/get-network-acls-by-id + * @param id the ID of the Network ACL to delete. + * @return a Request that can be executed to delete the Network ACL. + */ + public Request get(String id) { + Asserts.assertNotNull(id, "id"); + + String url = baseUrl.newBuilder() + .addPathSegments(ORGS_PATH) + .addPathSegment(id) + .build().toString(); + + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference(){}); + } + + /** + * Deletes a Network ACL by its ID. + * A token with scope delete:network_acls is needed. + * + * @see https://auth0.com/docs/api/management/v2#!/network-acls/delete-network-acls-by-id + * @param id the ID of the Network ACL to delete. + * @return a Request that can be executed to delete the Network ACL. + */ + public Request delete(String id) { + Asserts.assertNotNull(id, "id"); + + String url = baseUrl.newBuilder() + .addPathSegments(ORGS_PATH) + .addPathSegment(id) + .build().toString(); + + return new VoidRequest(client, tokenProvider, url, HttpMethod.DELETE); + } + + /** + * Updates a Network ACL by its ID. + * A token with scope update:network_acls is needed. + * + * @see https://auth0.com/docs/api/management/v2#!/network-acls/put-network-acls-by-id + * @param id the ID of the Network ACL to update. + * @param networkAcls the Network ACL to update. + * @return a Request that can be executed to update the Network ACL. + */ + public Request update(String id, NetworkAcls networkAcls) { + Asserts.assertNotNull(id, "id"); + Asserts.assertNotNull(networkAcls, "network acls"); + + String url = baseUrl.newBuilder() + .addPathSegments(ORGS_PATH) + .addPathSegment(id) + .build().toString(); + + BaseRequest request = new BaseRequest<>(client, tokenProvider, url, HttpMethod.PUT, new TypeReference() { + }); + request.setBody(networkAcls); + return request; + } + + /** + * Partially updates a Network ACL by its ID. + * A token with scope update:network_acls is needed. + * + * @see https://auth0.com/docs/api/management/v2#!/network-acls/patch-network-acls-by-id + * @param id the ID of the Network ACL to update. + * @param networkAcls the Network ACL to update. + * @return a Request that can be executed to partially update the Network ACL. + */ + public Request patch(String id, NetworkAcls networkAcls) { + Asserts.assertNotNull(id, "id"); + + String url = baseUrl.newBuilder() + .addPathSegments(ORGS_PATH) + .addPathSegment(id) + .build().toString(); + + BaseRequest request = new BaseRequest<>(client, tokenProvider, url, HttpMethod.PATCH, new TypeReference() { + }); + request.setBody(networkAcls); + return request; + } + +} diff --git a/src/main/java/com/auth0/client/mgmt/OrganizationsEntity.java b/src/main/java/com/auth0/client/mgmt/OrganizationsEntity.java index e47c56e53..dcb9f3ed1 100644 --- a/src/main/java/com/auth0/client/mgmt/OrganizationsEntity.java +++ b/src/main/java/com/auth0/client/mgmt/OrganizationsEntity.java @@ -1,18 +1,16 @@ package com.auth0.client.mgmt; -import com.auth0.client.mgmt.filter.BaseFilter; -import com.auth0.client.mgmt.filter.FieldsFilter; -import com.auth0.client.mgmt.filter.InvitationsFilter; -import com.auth0.client.mgmt.filter.PageFilter; -import com.auth0.json.mgmt.RolesPage; +import com.auth0.client.mgmt.filter.*; +import com.auth0.json.mgmt.roles.RolesPage; import com.auth0.json.mgmt.organizations.*; -import com.auth0.net.CustomRequest; +import com.auth0.net.BaseRequest; import com.auth0.net.Request; import com.auth0.net.VoidRequest; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.HttpMethod; import com.auth0.utils.Asserts; import com.fasterxml.jackson.core.type.TypeReference; import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; import java.util.Map; @@ -26,10 +24,9 @@ public class OrganizationsEntity extends BaseManagementEntity { private final static String ORGS_PATH = "api/v2/organizations"; - private final static String AUTHORIZATION_HEADER = "Authorization"; - OrganizationsEntity(OkHttpClient client, HttpUrl baseUrl, String apiToken) { - super(client, baseUrl, apiToken); + OrganizationsEntity(Auth0HttpClient client, HttpUrl baseUrl, TokenProvider tokenProvider) { + super(client, baseUrl, tokenProvider); } // Organizations Entity @@ -50,11 +47,9 @@ public Request list(PageFilter filter) { applyFilter(filter, builder); String url = builder.build().toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", new TypeReference() { - }); - request.addHeader(AUTHORIZATION_HEADER, "Bearer " + apiToken); - return request; + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { + }); } /** @@ -75,11 +70,8 @@ public Request get(String orgId) { .build() .toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", new TypeReference() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { }); - - request.addHeader(AUTHORIZATION_HEADER, "Bearer " + apiToken); - return request; } /** @@ -101,11 +93,8 @@ public Request getByName(String orgName) { .build() .toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", new TypeReference() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { }); - - request.addHeader(AUTHORIZATION_HEADER, "Bearer " + apiToken); - return request; } /** @@ -125,10 +114,9 @@ public Request create(Organization organization) { .build() .toString(); - CustomRequest request = new CustomRequest<>(client, url, "POST", new TypeReference() { + BaseRequest request = new BaseRequest<>(client, tokenProvider, url, HttpMethod.POST, new TypeReference() { }); - request.addHeader(AUTHORIZATION_HEADER, "Bearer " + apiToken); request.setBody(organization); return request; } @@ -153,10 +141,9 @@ public Request update(String orgId, Organization organization) { .build() .toString(); - CustomRequest request = new CustomRequest<>(client, url, "PATCH", new TypeReference() { + BaseRequest request = new BaseRequest<>(client, tokenProvider, url, HttpMethod.PATCH, new TypeReference() { }); - request.addHeader(AUTHORIZATION_HEADER, "Bearer " + apiToken); request.setBody(organization); return request; } @@ -179,9 +166,7 @@ public Request delete(String orgId) { .build() .toString(); - VoidRequest voidRequest = new VoidRequest(client, url, "DELETE"); - voidRequest.addHeader(AUTHORIZATION_HEADER, "Bearer " + apiToken); - return voidRequest; + return new VoidRequest(client, tokenProvider, url, HttpMethod.DELETE); } // Organization members @@ -196,6 +181,22 @@ public Request delete(String orgId) { * @see https://auth0.com/docs/api/management/v2#!/Organizations/get_members */ public Request getMembers(String orgId, PageFilter filter) { + return getMembers(orgId, filter, null); + } + + /** + * Get the members of an organization. A token with {@code read:organization_members} scope is required. + *
+ * Member roles are not sent by default. Supply a {@linkplain FieldsFilter} that includes "roles" (and {@code includeFields = true} to retrieve the roles assigned to each listed member. To include the roles in the response, you must include the {@code read:organization_member_roles} scope in the token. + * + * @param orgId the ID of the organization + * @param pageFilter an optional pagination filter + * @param fieldsFilter an optional fields filter. If null, all fields (except roles) are returned. + * @return a Request to execute + * + * @see https://auth0.com/docs/api/management/v2#!/Organizations/get_members + */ + public Request getMembers(String orgId, PageFilter pageFilter, FieldsFilter fieldsFilter) { Asserts.assertNotNull(orgId, "organization ID"); HttpUrl.Builder builder = baseUrl @@ -204,13 +205,12 @@ public Request getMembers(String orgId, PageFilter filter) { .addPathSegment(orgId) .addPathSegment("members"); - applyFilter(filter, builder); + applyFilter(pageFilter, builder); + applyFilter(fieldsFilter, builder); String url = builder.build().toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", new TypeReference() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { }); - request.addHeader(AUTHORIZATION_HEADER, "Bearer " + apiToken); - return request; } /** @@ -234,8 +234,7 @@ public Request addMembers(String orgId, Members members) { .build() .toString(); - VoidRequest request = new VoidRequest(client, url, "POST"); - request.addHeader(AUTHORIZATION_HEADER, "Bearer " + apiToken); + VoidRequest request = new VoidRequest(client, tokenProvider, url, HttpMethod.POST); request.setBody(members); return request; } @@ -261,8 +260,7 @@ public Request deleteMembers(String orgId, Members members) { .build() .toString(); - VoidRequest request = new VoidRequest(client, url, "DELETE"); - request.addHeader(AUTHORIZATION_HEADER, "Bearer " + apiToken); + VoidRequest request = new VoidRequest(client, tokenProvider, url, HttpMethod.DELETE); request.setBody(members); return request; } @@ -290,10 +288,8 @@ public Request getConnections(String orgId, PageFilter f applyFilter(filter, builder); String url = builder.build().toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", new TypeReference() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { }); - request.addHeader(AUTHORIZATION_HEADER, "Bearer " + apiToken); - return request; } /** @@ -318,10 +314,8 @@ public Request getConnection(String orgId, String connectionI .build() .toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", new TypeReference() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { }); - request.addHeader(AUTHORIZATION_HEADER, "Bearer " + apiToken); - return request; } /** @@ -345,9 +339,8 @@ public Request addConnection(String orgId, EnabledConnection .build() .toString(); - CustomRequest request = new CustomRequest<>(client, url, "POST", new TypeReference() { + BaseRequest request = new BaseRequest<>(client, tokenProvider, url, HttpMethod.POST, new TypeReference() { }); - request.addHeader(AUTHORIZATION_HEADER, "Bearer " + apiToken); request.setBody(connection); return request; } @@ -374,9 +367,7 @@ public Request deleteConnection(String orgId, String connectionId) { .build() .toString(); - VoidRequest voidRequest = new VoidRequest(client, url, "DELETE"); - voidRequest.addHeader(AUTHORIZATION_HEADER, "Bearer " + apiToken); - return voidRequest; + return new VoidRequest(client, tokenProvider, url, HttpMethod.DELETE); } /** @@ -403,9 +394,8 @@ public Request updateConnection(String orgId, String connecti .build() .toString(); - CustomRequest request = new CustomRequest<>(client, url, "PATCH", new TypeReference() { + BaseRequest request = new BaseRequest<>(client, tokenProvider, url, HttpMethod.PATCH, new TypeReference() { }); - request.addHeader(AUTHORIZATION_HEADER, "Bearer " + apiToken); request.setBody(connection); return request; } @@ -437,10 +427,8 @@ public Request getRoles(String orgId, String userId, PageFilter filte applyFilter(filter, builder); String url = builder.build().toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", new TypeReference() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { }); - request.addHeader(AUTHORIZATION_HEADER, "Bearer " + apiToken); - return request; } /** @@ -468,8 +456,7 @@ public Request addRoles(String orgId, String userId, Roles roles) { .build() .toString(); - VoidRequest request = new VoidRequest(client, url, "POST"); - request.addHeader(AUTHORIZATION_HEADER, "Bearer " + apiToken); + VoidRequest request = new VoidRequest(client, tokenProvider, url, HttpMethod.POST); request.setBody(roles); return request; } @@ -499,8 +486,7 @@ public Request deleteRoles(String orgId, String userId, Roles roles) { .build() .toString(); - VoidRequest request = new VoidRequest(client, url, "DELETE"); - request.addHeader(AUTHORIZATION_HEADER, "Bearer " + apiToken); + VoidRequest request = new VoidRequest(client, tokenProvider, url, HttpMethod.DELETE); request.setBody(roles); return request; } @@ -528,9 +514,8 @@ public Request createInvitation(String orgId, Invitation invitation) .build() .toString(); - CustomRequest request = new CustomRequest<>(client, url, "POST", new TypeReference() { + BaseRequest request = new BaseRequest<>(client, tokenProvider, url, HttpMethod.POST, new TypeReference() { }); - request.addHeader(AUTHORIZATION_HEADER, "Bearer " + apiToken); request.setBody(invitation); return request; @@ -560,10 +545,8 @@ public Request getInvitation(String orgId, String invitationId, Fiel applyFilter(filter, builder); String url = builder.build().toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", new TypeReference() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { }); - request.addHeader(AUTHORIZATION_HEADER, "Bearer " + apiToken); - return request; } /** @@ -587,10 +570,8 @@ public Request getInvitations(String orgId, InvitationsFilter f applyFilter(filter, builder); String url = builder.build().toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", new TypeReference() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { }); - request.addHeader(AUTHORIZATION_HEADER, "Bearer " + apiToken); - return request; } /** @@ -615,11 +596,76 @@ public Request deleteInvitation(String orgId, String invitationId) { .build() .toString(); - VoidRequest request = new VoidRequest(client, url, "DELETE"); - request.addHeader(AUTHORIZATION_HEADER, "Bearer " + apiToken); + return new VoidRequest(client, tokenProvider, url, HttpMethod.DELETE); + } + + /** + * Get the client grants associated with this organization. A token with scope {@code read:organization_client_grants} is required. + * @param orgId the organization ID. + * @param filter an optional filter to refine results. + * @return a request to execute. + */ + public Request listClientGrants(String orgId, OrganizationClientGrantsFilter filter) { + Asserts.assertNotNull(orgId, "organization ID"); + + HttpUrl.Builder builder = baseUrl + .newBuilder() + .addPathSegments(ORGS_PATH) + .addPathSegments(orgId) + .addPathSegment("client-grants"); + + applyFilter(filter, builder); + + String url = builder.build().toString(); + + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() {}); + } + + /** + * Associate a client grant with an organization. A token with scope {@code create:organization_client_grants} is required. + * @param orgId the organization ID. + * @param addOrganizationClientGrantRequestBody the body of the request containing information about the client grant to associate. + * @return a request to execute. + */ + public Request addClientGrant(String orgId, CreateOrganizationClientGrantRequestBody addOrganizationClientGrantRequestBody) { + Asserts.assertNotNull(orgId, "organization ID"); + Asserts.assertNotNull(addOrganizationClientGrantRequestBody, "client grant"); + + String url = baseUrl + .newBuilder() + .addPathSegments(ORGS_PATH) + .addPathSegment(orgId) + .addPathSegment("client-grants") + .build() + .toString(); + + BaseRequest request = new BaseRequest<>(client, tokenProvider, url, HttpMethod.POST, new TypeReference() {}); + request.setBody(addOrganizationClientGrantRequestBody); return request; } + /** + * Remove a client grant from an organization. A token with scope {@code delete:organization_client_grants} is required. + * @param orgId the organization ID. + * @param grantId the client grant ID. + * @return a request to execute. + */ + public Request deleteClientGrant(String orgId, String grantId) { + Asserts.assertNotNull(orgId, "organization ID"); + Asserts.assertNotNull(grantId, "client grant ID"); + + String url = baseUrl + .newBuilder() + .addPathSegments(ORGS_PATH) + .addPathSegment(orgId) + .addPathSegment("client-grants") + .addPathSegment(grantId) + .build() + .toString(); + + return new VoidRequest(client, tokenProvider, url, HttpMethod.DELETE); + } + private void applyFilter(BaseFilter filter, HttpUrl.Builder builder) { if (filter != null) { for (Map.Entry e : filter.getAsMap().entrySet()) { diff --git a/src/main/java/com/auth0/client/mgmt/PromptsEntity.java b/src/main/java/com/auth0/client/mgmt/PromptsEntity.java new file mode 100644 index 000000000..3c26546e5 --- /dev/null +++ b/src/main/java/com/auth0/client/mgmt/PromptsEntity.java @@ -0,0 +1,162 @@ +package com.auth0.client.mgmt; + +import com.auth0.json.mgmt.prompts.Prompt; +import com.auth0.net.BaseRequest; +import com.auth0.net.Request; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.HttpMethod; +import com.auth0.utils.Asserts; +import com.fasterxml.jackson.core.type.TypeReference; +import okhttp3.HttpUrl; + +public class PromptsEntity extends BaseManagementEntity { + + private final static String ORGS_PATH = "api/v2/prompts"; + + PromptsEntity(Auth0HttpClient client, HttpUrl baseUrl, TokenProvider tokenProvider) { + super(client, baseUrl, tokenProvider); + } + + /** + * Get the prompt. + * A token with {@code read:prompts} scope is required. + * @return a Request to execute. + * + * @see https://auth0.com/docs/api/management/v2#!/prompts/get-prompts + */ + public Request getPrompt() { + HttpUrl.Builder builder = baseUrl.newBuilder() + .addPathSegments(ORGS_PATH); + String url = builder.build().toString(); + + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { + }); + } + + /** + * Update the prompt. + * A token with {@code update:prompts} scope is required. + * @param prompt the prompt to update. + * @return a Request to execute. + * + * @see https://auth0.com/docs/api/management/v2#!/prompts/patch-prompts + */ + public Request updatePrompt(Prompt prompt) { + Asserts.assertNotNull(prompt, "prompt"); + + HttpUrl.Builder builder = baseUrl.newBuilder() + .addPathSegments(ORGS_PATH); + String url = builder.build().toString(); + + BaseRequest request = new BaseRequest<>(client, tokenProvider, url, HttpMethod.PATCH, new TypeReference() { + }); + + request.setBody(prompt); + return request; + } + + /** + * Get the custom text for specific prompt and language. + * A token with {@code read:prompts} scope is required. + * @param prompt the prompt name. + * @param language the language. + * @return a Request to execute. + * + * @see https://auth0.com/docs/api/management/v2#!/prompts/get-custom-text-by-language + */ + public Request getCustomText(String prompt, String language) { + Asserts.assertNotNull(prompt, "prompt"); + Asserts.assertNotNull(language, "language"); + + HttpUrl.Builder builder = baseUrl.newBuilder() + .addPathSegments(ORGS_PATH) + .addPathSegment(prompt) + .addPathSegment("custom-text") + .addPathSegment(language); + + String url = builder.build().toString(); + + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { + }); + } + + /** + * Set the custom text for specific prompt and language. + * A token with {@code update:prompts} scope is required. + * @param prompt the prompt name. + * @param language the language. + * @param customText the custom text. + * @return a Request to execute. + * + * @see https://auth0.com/docs/api/management/v2#!/prompts/put-custom-text-by-language + */ + public Request setCustomText(String prompt, String language, Object customText) { + Asserts.assertNotNull(prompt, "prompt"); + Asserts.assertNotNull(language, "language"); + Asserts.assertNotNull(customText, "customText"); + + HttpUrl.Builder builder = baseUrl.newBuilder() + .addPathSegments(ORGS_PATH) + .addPathSegment(prompt) + .addPathSegment("custom-text") + .addPathSegment(language); + + String url = builder.build().toString(); + + BaseRequest request = new BaseRequest<>(client, tokenProvider, url, HttpMethod.PUT, new TypeReference() { + }); + + request.setBody(customText); + return request; + } + + /** + * Get the partials for specific prompt. + * A token with {@code read:prompts} scope is required. + * @param prompt the prompt name. + * @return a Request to execute. + * + * @see https://auth0.com/docs/api/management/v2#!/prompts/get-partials + */ + public Request getPartialsPrompt(String prompt) { + Asserts.assertNotNull(prompt, "prompt"); + + HttpUrl.Builder builder = baseUrl.newBuilder() + .addPathSegments(ORGS_PATH) + .addPathSegment(prompt) + .addPathSegment("partials"); + + String url = builder.build().toString(); + + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { + }); + } + + /** + * Set the partials for specific prompt. + * A token with {@code read:prompts} scope is required. + * @param prompt the prompt name. + * @param partials the partials. + * @return a Request to execute. + * + * @see https://auth0.com/docs/api/management/v2#!/prompts/put-partials + */ + public Request setPartialsPrompt(String prompt, Object partials) { + Asserts.assertNotNull(prompt, "prompt"); + Asserts.assertNotNull(partials, "partials"); + + HttpUrl.Builder builder = baseUrl.newBuilder() + .addPathSegments(ORGS_PATH) + .addPathSegment(prompt) + .addPathSegment("partials"); + + String url = builder.build().toString(); + + BaseRequest request = new BaseRequest<>(client, tokenProvider, url, HttpMethod.PUT, new TypeReference() { + }); + + request.setBody(partials); + return request; + } + +} diff --git a/src/main/java/com/auth0/client/mgmt/RefreshTokensEntity.java b/src/main/java/com/auth0/client/mgmt/RefreshTokensEntity.java new file mode 100644 index 000000000..6911aef2e --- /dev/null +++ b/src/main/java/com/auth0/client/mgmt/RefreshTokensEntity.java @@ -0,0 +1,66 @@ +package com.auth0.client.mgmt; + +import com.auth0.json.mgmt.refreshtokens.RefreshToken; +import com.auth0.net.BaseRequest; +import com.auth0.net.Request; +import com.auth0.net.VoidRequest; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.HttpMethod; +import com.auth0.utils.Asserts; +import com.fasterxml.jackson.core.type.TypeReference; +import okhttp3.HttpUrl; + +/** + * Class that provides an implementation of the Refresh Tokens methods of the Management API as defined in https://auth0.com/docs/api/management/v2#!/Refresh_Tokens + *

+ * This class is not thread-safe. + * @see ManagementAPI + */ +@SuppressWarnings("WeakerAccess") +public class RefreshTokensEntity extends BaseManagementEntity{ + + RefreshTokensEntity(Auth0HttpClient client, HttpUrl baseUrl, TokenProvider tokenProvider) { + super(client, baseUrl, tokenProvider); + } + + /** + * Request the refresh token for a given refresh token ID. + * A token with scope {@code read:refresh_tokens} is needed. + * See https://auth0.com/docs/api/management/v2/refresh-tokens/get-refresh-token + * @param refreshTokenId the refresh token ID. + * @return a Request to execute. + */ + public Request get(String refreshTokenId){ + Asserts.assertNotNull(refreshTokenId, "refresh token ID"); + + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/refresh-tokens") + .addPathSegment(refreshTokenId) + .build() + .toString(); + + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { + }); + } + + /** + * Delete the refresh token for a given refresh token ID. + * * A token with scope {@code delete:refresh_tokens} is needed. + * See https://auth0.com/docs/api/management/v2/refresh-tokens/delete-refresh-token + * @param refreshTokenId the refresh token ID. + * @return a Request to execute. + */ + public Request delete(String refreshTokenId){ + Asserts.assertNotNull(refreshTokenId, "refresh token ID"); + + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/refresh-tokens") + .addPathSegment(refreshTokenId) + .build() + .toString(); + + return new VoidRequest(client, tokenProvider, url, HttpMethod.DELETE); + } +} diff --git a/src/main/java/com/auth0/client/mgmt/RequestBuilder.java b/src/main/java/com/auth0/client/mgmt/RequestBuilder.java index 8eb32e52e..2f8c0f3d0 100644 --- a/src/main/java/com/auth0/client/mgmt/RequestBuilder.java +++ b/src/main/java/com/auth0/client/mgmt/RequestBuilder.java @@ -1,20 +1,21 @@ package com.auth0.client.mgmt; -import com.auth0.net.CustomRequest; +import com.auth0.net.BaseRequest; import com.auth0.net.Request; import com.auth0.net.VoidRequest; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.HttpMethod; import com.fasterxml.jackson.core.type.TypeReference; +import okhttp3.HttpUrl; +import org.jetbrains.annotations.Nullable; import java.util.HashMap; import java.util.Map; -import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; -import org.jetbrains.annotations.Nullable; - class RequestBuilder { - private final OkHttpClient client; - private final String method; + private final Auth0HttpClient client; + private final TokenProvider tokenProvider; + private final HttpMethod method; private final HttpUrl.Builder url; private final TypeReference target; @@ -23,8 +24,9 @@ class RequestBuilder { private final Map headers = new HashMap<>(); private final Map parameters = new HashMap<>(); - public RequestBuilder(OkHttpClient client, String method, HttpUrl baseUrl, TypeReference target) { + public RequestBuilder(Auth0HttpClient client, TokenProvider tokenProvider, HttpMethod method, HttpUrl baseUrl, TypeReference target) { this.client = client; + this.tokenProvider = tokenProvider; this.method = method; this.url = baseUrl.newBuilder(); this.target = target; @@ -52,13 +54,13 @@ public RequestBuilder withPathSegments(String path) { @SuppressWarnings("unchecked") public Request build() { - CustomRequest request; + BaseRequest request; final String url = this.url.build().toString(); if ("java.lang.Void".equals(target.getType().getTypeName())) { - request = (CustomRequest) new VoidRequest(client, url, method); + request = (BaseRequest) new VoidRequest(client, tokenProvider, url, method); } else { - request = new CustomRequest<>(client, url, method, target); + request = new BaseRequest<>(client, tokenProvider, url, method, target); } if (body != null) { diff --git a/src/main/java/com/auth0/client/mgmt/ResourceServerEntity.java b/src/main/java/com/auth0/client/mgmt/ResourceServerEntity.java index a586cfb6f..b9c271f0e 100644 --- a/src/main/java/com/auth0/client/mgmt/ResourceServerEntity.java +++ b/src/main/java/com/auth0/client/mgmt/ResourceServerEntity.java @@ -1,15 +1,16 @@ package com.auth0.client.mgmt; import com.auth0.client.mgmt.filter.ResourceServersFilter; -import com.auth0.json.mgmt.ResourceServer; -import com.auth0.json.mgmt.ResourceServersPage; -import com.auth0.net.CustomRequest; +import com.auth0.json.mgmt.resourceserver.ResourceServer; +import com.auth0.json.mgmt.resourceserver.ResourceServersPage; +import com.auth0.net.BaseRequest; import com.auth0.net.Request; import com.auth0.net.VoidRequest; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.HttpMethod; import com.auth0.utils.Asserts; import com.fasterxml.jackson.core.type.TypeReference; import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; import java.util.List; import java.util.Map; @@ -23,8 +24,8 @@ */ public class ResourceServerEntity extends BaseManagementEntity { - ResourceServerEntity(OkHttpClient client, HttpUrl baseUrl, String apiToken) { - super(client, baseUrl, apiToken); + ResourceServerEntity(Auth0HttpClient client, HttpUrl baseUrl, TokenProvider tokenProvider) { + super(client, baseUrl, tokenProvider); } /** @@ -45,33 +46,9 @@ public Request list(ResourceServersFilter filter) { } String url = builder.build().toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; - } - - /** - * Creates request to fetch all resource servers. - * See API documentation - * - * @return request to execute - * @deprecated Calling this method will soon stop returning the complete list of resource servers and instead, limit to the first page of results. - * Please use {@link #list(ResourceServersFilter)} instead as it provides pagination support. - */ - @Deprecated - public Request> list() { - HttpUrl.Builder builder = baseUrl - .newBuilder() - .addPathSegments("api/v2/resource-servers"); - - String url = builder.build().toString(); - CustomRequest> request = new CustomRequest<>(client, url, "GET", - new TypeReference>() { - }); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; } /** @@ -90,11 +67,9 @@ public Request get(String resourceServerIdOrIdentifier) { .addPathSegment(resourceServerIdOrIdentifier); String url = builder.build().toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; } /** @@ -112,10 +87,9 @@ public Request create(ResourceServer resourceServer) { .addPathSegments("api/v2/resource-servers"); String url = builder.build().toString(); - CustomRequest request = new CustomRequest<>(client, url, "POST", + BaseRequest request = new BaseRequest<>(client, tokenProvider, url, HttpMethod.POST, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); request.setBody(resourceServer); return request; } @@ -136,9 +110,7 @@ public Request delete(String resourceServerId) { .addPathSegment(resourceServerId); String url = builder.build().toString(); - VoidRequest request = new VoidRequest(client, url, "DELETE"); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; + return new VoidRequest(client, tokenProvider, url, HttpMethod.DELETE); } /** @@ -159,10 +131,9 @@ public Request update(String resourceServerId, ResourceServer re .addPathSegment(resourceServerId); String url = builder.build().toString(); - CustomRequest request = new CustomRequest(client, url, "PATCH", - new TypeReference() { - }); - request.addHeader("Authorization", "Bearer " + apiToken); + BaseRequest request = new BaseRequest<>(client, tokenProvider, url, HttpMethod.PATCH, + new TypeReference() { + }); request.setBody(resourceServer); return request; } diff --git a/src/main/java/com/auth0/client/mgmt/RolesEntity.java b/src/main/java/com/auth0/client/mgmt/RolesEntity.java index 4edb65c27..69edd7a5c 100644 --- a/src/main/java/com/auth0/client/mgmt/RolesEntity.java +++ b/src/main/java/com/auth0/client/mgmt/RolesEntity.java @@ -2,18 +2,19 @@ import com.auth0.client.mgmt.filter.PageFilter; import com.auth0.client.mgmt.filter.RolesFilter; -import com.auth0.json.mgmt.Permission; -import com.auth0.json.mgmt.PermissionsPage; -import com.auth0.json.mgmt.Role; -import com.auth0.json.mgmt.RolesPage; +import com.auth0.json.mgmt.permissions.Permission; +import com.auth0.json.mgmt.permissions.PermissionsPage; +import com.auth0.json.mgmt.roles.Role; +import com.auth0.json.mgmt.roles.RolesPage; import com.auth0.json.mgmt.users.UsersPage; -import com.auth0.net.CustomRequest; +import com.auth0.net.BaseRequest; import com.auth0.net.Request; import com.auth0.net.VoidRequest; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.HttpMethod; import com.auth0.utils.Asserts; import com.fasterxml.jackson.core.type.TypeReference; import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; import java.util.HashMap; import java.util.List; @@ -28,9 +29,9 @@ */ public class RolesEntity extends BaseManagementEntity { - RolesEntity(OkHttpClient client, HttpUrl baseUrl, - String apiToken) { - super(client, baseUrl, apiToken); + RolesEntity(Auth0HttpClient client, HttpUrl baseUrl, + TokenProvider tokenProvider) { + super(client, baseUrl, tokenProvider); } /** @@ -51,9 +52,7 @@ public Request list(RolesFilter filter) { } } String url = builder.build().toString(); - CustomRequest request = new CustomRequest<>(this.client, url, "GET", new TypeReference() {}); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; + return new BaseRequest<>(this.client, tokenProvider, url, HttpMethod.GET, new TypeReference() {}); } /** @@ -70,12 +69,10 @@ public Request get(String roleId) { HttpUrl.Builder builder = baseUrl .newBuilder() .addEncodedPathSegments("api/v2/roles") - .addEncodedPathSegments(roleId); + .addEncodedPathSegment(roleId); String url = builder.build().toString(); - CustomRequest request = new CustomRequest<>(this.client, url, "GET", new TypeReference() {}); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; + return new BaseRequest<>(this.client, tokenProvider, url, HttpMethod.GET, new TypeReference() {}); } @@ -95,8 +92,7 @@ public Request create(Role role) { .addEncodedPathSegments("api/v2/roles") .build() .toString(); - CustomRequest request = new CustomRequest<>(this.client, url, "POST", new TypeReference() {}); - request.addHeader("Authorization", "Bearer " + apiToken); + BaseRequest request = new BaseRequest<>(this.client, tokenProvider, url, HttpMethod.POST, new TypeReference() {}); request.setBody(role); return request; } @@ -115,12 +111,10 @@ public Request delete(String roleId) { final String url = baseUrl .newBuilder() .addEncodedPathSegments("api/v2/roles") - .addEncodedPathSegments(roleId) + .addEncodedPathSegment(roleId) .build() .toString(); - VoidRequest request = new VoidRequest(this.client, url, "DELETE"); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; + return new VoidRequest(this.client, tokenProvider, url, HttpMethod.DELETE); } /** @@ -139,11 +133,10 @@ public Request update(String roleId, Role role) { String url = baseUrl .newBuilder() .addEncodedPathSegments("api/v2/roles") - .addEncodedPathSegments(roleId) + .addEncodedPathSegment(roleId) .build() .toString(); - CustomRequest request = new CustomRequest<>(this.client, url, "PATCH", new TypeReference() {}); - request.addHeader("Authorization", "Bearer " + apiToken); + BaseRequest request = new BaseRequest<>(this.client, tokenProvider, url, HttpMethod.PATCH, new TypeReference() {}); request.setBody(role); return request; } @@ -163,17 +156,15 @@ public Request listUsers(String roleId, PageFilter filter) { HttpUrl.Builder builder = baseUrl .newBuilder() .addEncodedPathSegments("api/v2/roles") - .addEncodedPathSegments(roleId) - .addEncodedPathSegments("users"); + .addEncodedPathSegment(roleId) + .addEncodedPathSegment("users"); if (filter != null) { for (Map.Entry e : filter.getAsMap().entrySet()) { builder.addQueryParameter(e.getKey(), String.valueOf(e.getValue())); } } String url = builder.build().toString(); - CustomRequest request = new CustomRequest<>(this.client, url, "GET", new TypeReference() {}); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; + return new BaseRequest<>(this.client, tokenProvider, url, HttpMethod.GET, new TypeReference() {}); } /** @@ -195,12 +186,11 @@ public Request assignUsers(String roleId, List userIds) { String url = baseUrl .newBuilder() .addEncodedPathSegments("api/v2/roles") - .addEncodedPathSegments(roleId) - .addEncodedPathSegments("users") + .addEncodedPathSegment(roleId) + .addEncodedPathSegment("users") .build() .toString(); - VoidRequest request = new VoidRequest(this.client, url, "POST"); - request.addHeader("Authorization", "Bearer " + apiToken); + VoidRequest request = new VoidRequest(this.client, tokenProvider, url, HttpMethod.POST); request.setBody(body); return request; } @@ -220,17 +210,15 @@ public Request listPermissions(String roleId, PageFilter filter HttpUrl.Builder builder = baseUrl .newBuilder() .addEncodedPathSegments("api/v2/roles") - .addEncodedPathSegments(roleId) - .addEncodedPathSegments("permissions"); + .addEncodedPathSegment(roleId) + .addEncodedPathSegment("permissions"); if (filter != null) { for (Map.Entry e : filter.getAsMap().entrySet()) { builder.addQueryParameter(e.getKey(), String.valueOf(e.getValue())); } } String url = builder.build().toString(); - CustomRequest request = new CustomRequest<>(this.client, url, "GET", new TypeReference() {}); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; + return new BaseRequest<>(this.client, tokenProvider, url, HttpMethod.GET, new TypeReference() {}); } /** @@ -252,13 +240,12 @@ public Request removePermissions(String roleId, List permissio final String url = baseUrl .newBuilder() .addEncodedPathSegments("api/v2/roles") - .addEncodedPathSegments(roleId) - .addEncodedPathSegments("permissions") + .addEncodedPathSegment(roleId) + .addEncodedPathSegment("permissions") .build() .toString(); - VoidRequest request = new VoidRequest(this.client, url, "DELETE"); + VoidRequest request = new VoidRequest(this.client, tokenProvider, url, HttpMethod.DELETE); request.setBody(body); - request.addHeader("Authorization", "Bearer " + apiToken); return request; } @@ -282,13 +269,12 @@ public Request addPermissions(String roleId, List permissions) final String url = baseUrl .newBuilder() .addEncodedPathSegments("api/v2/roles") - .addEncodedPathSegments(roleId) - .addEncodedPathSegments("permissions") + .addEncodedPathSegment(roleId) + .addEncodedPathSegment("permissions") .build() .toString(); - VoidRequest request = new VoidRequest(this.client, url, "POST"); + VoidRequest request = new VoidRequest(this.client, tokenProvider, url, HttpMethod.POST); request.setBody(body); - request.addHeader("Authorization", "Bearer " + apiToken); return request; } } diff --git a/src/main/java/com/auth0/client/mgmt/RulesConfigsEntity.java b/src/main/java/com/auth0/client/mgmt/RulesConfigsEntity.java index 5bdb4edf2..ac4c740b5 100644 --- a/src/main/java/com/auth0/client/mgmt/RulesConfigsEntity.java +++ b/src/main/java/com/auth0/client/mgmt/RulesConfigsEntity.java @@ -1,13 +1,14 @@ package com.auth0.client.mgmt; -import com.auth0.json.mgmt.RulesConfig; -import com.auth0.net.CustomRequest; +import com.auth0.json.mgmt.rules.RulesConfig; +import com.auth0.net.BaseRequest; import com.auth0.net.Request; import com.auth0.net.VoidRequest; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.HttpMethod; import com.auth0.utils.Asserts; import com.fasterxml.jackson.core.type.TypeReference; import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; import java.util.List; @@ -21,8 +22,8 @@ @SuppressWarnings("WeakerAccess") public class RulesConfigsEntity extends BaseManagementEntity { - RulesConfigsEntity(OkHttpClient client, HttpUrl baseUrl, String apiToken) { - super(client, baseUrl, apiToken); + RulesConfigsEntity(Auth0HttpClient client, HttpUrl baseUrl, TokenProvider tokenProvider) { + super(client, baseUrl, tokenProvider); } /** @@ -38,10 +39,8 @@ public Request> list() { .newBuilder() .addPathSegments("api/v2/rules-configs"); String url = builder.build().toString(); - CustomRequest> request = new CustomRequest<>(client, url, "GET", new TypeReference>() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference>() { }); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; } /** @@ -60,9 +59,7 @@ public Request delete(String rulesConfigKey) { .addPathSegment(rulesConfigKey) .build() .toString(); - VoidRequest request = new VoidRequest(client, url, "DELETE"); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; + return new VoidRequest(client, tokenProvider, url, HttpMethod.DELETE); } /** @@ -83,9 +80,8 @@ public Request update(String rulesConfigKey, RulesConfig rulesConfi .addPathSegment(rulesConfigKey) .build() .toString(); - CustomRequest request = new CustomRequest<>(this.client, url, "PUT", new TypeReference() { + BaseRequest request = new BaseRequest<>(this.client, tokenProvider, url, HttpMethod.PUT, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); request.setBody(rulesConfig); return request; } diff --git a/src/main/java/com/auth0/client/mgmt/RulesEntity.java b/src/main/java/com/auth0/client/mgmt/RulesEntity.java index aa1558efd..4cf81843f 100644 --- a/src/main/java/com/auth0/client/mgmt/RulesEntity.java +++ b/src/main/java/com/auth0/client/mgmt/RulesEntity.java @@ -1,15 +1,16 @@ package com.auth0.client.mgmt; import com.auth0.client.mgmt.filter.RulesFilter; -import com.auth0.json.mgmt.Rule; -import com.auth0.json.mgmt.RulesPage; -import com.auth0.net.CustomRequest; +import com.auth0.json.mgmt.rules.Rule; +import com.auth0.json.mgmt.rules.RulesPage; +import com.auth0.net.BaseRequest; import com.auth0.net.Request; import com.auth0.net.VoidRequest; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.HttpMethod; import com.auth0.utils.Asserts; import com.fasterxml.jackson.core.type.TypeReference; import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; import java.util.List; import java.util.Map; @@ -24,8 +25,8 @@ @SuppressWarnings("WeakerAccess") public class RulesEntity extends BaseManagementEntity { - RulesEntity(OkHttpClient client, HttpUrl baseUrl, String apiToken) { - super(client, baseUrl, apiToken); + RulesEntity(Auth0HttpClient client, HttpUrl baseUrl, TokenProvider tokenProvider) { + super(client, baseUrl, tokenProvider); } /** @@ -45,39 +46,8 @@ public Request listAll(RulesFilter filter) { } } String url = builder.build().toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", new TypeReference() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; - } - - /** - * Request all the Rules. A token with scope read:rules is needed. - * See https://auth0.com/docs/api/management/v2#!/Rules/get_rules - * - * @param filter the filter to use. Can be null. - * @return a Request to execute. - * @deprecated Calling this method will soon stop returning the complete list of rules and instead, limit to the first page of results. - * Please use {@link #listAll(RulesFilter)} instead as it provides pagination support. - */ - @Deprecated - public Request> list(RulesFilter filter) { - HttpUrl.Builder builder = baseUrl - .newBuilder() - .addPathSegments("api/v2/rules"); - if (filter != null) { - for (Map.Entry e : filter.getAsMap().entrySet()) { - //This check below is to prevent JSON parsing errors - if (!e.getKey().equalsIgnoreCase("include_totals")) { - builder.addQueryParameter(e.getKey(), String.valueOf(e.getValue())); - } - } - } - String url = builder.build().toString(); - CustomRequest> request = new CustomRequest<>(client, url, "GET", new TypeReference>() { - }); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; } /** @@ -101,10 +71,8 @@ public Request get(String ruleId, RulesFilter filter) { } } String url = builder.build().toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", new TypeReference() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; } /** @@ -122,9 +90,8 @@ public Request create(Rule rule) { .addPathSegments("api/v2/rules") .build() .toString(); - CustomRequest request = new CustomRequest<>(this.client, url, "POST", new TypeReference() { + BaseRequest request = new BaseRequest<>(this.client, tokenProvider, url, HttpMethod.POST, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); request.setBody(rule); return request; } @@ -145,9 +112,7 @@ public Request delete(String ruleId) { .addPathSegment(ruleId) .build() .toString(); - VoidRequest request = new VoidRequest(client, url, "DELETE"); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; + return new VoidRequest(client, tokenProvider, url, HttpMethod.DELETE); } /** @@ -168,9 +133,8 @@ public Request update(String ruleId, Rule rule) { .addPathSegment(ruleId) .build() .toString(); - CustomRequest request = new CustomRequest<>(this.client, url, "PATCH", new TypeReference() { + BaseRequest request = new BaseRequest<>(this.client, tokenProvider, url, HttpMethod.PATCH, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); request.setBody(rule); return request; } diff --git a/src/main/java/com/auth0/client/mgmt/SelfServiceProfilesEntity.java b/src/main/java/com/auth0/client/mgmt/SelfServiceProfilesEntity.java new file mode 100644 index 000000000..38d9373b3 --- /dev/null +++ b/src/main/java/com/auth0/client/mgmt/SelfServiceProfilesEntity.java @@ -0,0 +1,265 @@ +package com.auth0.client.mgmt; + +import com.auth0.client.auth.AuthAPI; +import com.auth0.client.mgmt.filter.PageBasedPaginationFilter; +import com.auth0.json.mgmt.selfserviceprofiles.*; +import com.auth0.net.*; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.HttpMethod; +import com.auth0.utils.Asserts; +import com.fasterxml.jackson.core.type.TypeReference; +import okhttp3.HttpUrl; + +import java.util.Map; + +public class SelfServiceProfilesEntity extends BaseManagementEntity { + + private final static String ORGS_PATH = "api/v2/self-service-profiles"; + + SelfServiceProfilesEntity(Auth0HttpClient client, HttpUrl baseUrl, TokenProvider tokenProvider) { + super(client, baseUrl, tokenProvider); + } + + /** + * Request the list of self-service profiles. + * A token with {@code read:self_service_profiles} scope is needed + * @see https://auth0.com/docs/api/management/v2#!/self-service-profiles/get-self-service-profiles + * @param pageFilter the pagination filter to apply. Can be null to use the default values. + * @return a Request to execute. + */ + public Request get(PageBasedPaginationFilter pageFilter) { + HttpUrl.Builder builder = baseUrl.newBuilder() + .addPathSegments(ORGS_PATH); + + if (pageFilter != null) { + for (Map.Entry e : pageFilter.getAsMap().entrySet()) { + builder.addQueryParameter(e.getKey(), String.valueOf(e.getValue())); + } + } + + String url = builder.build().toString(); + return new BaseRequest<>(this.client, tokenProvider, url, HttpMethod.GET, new TypeReference() { + }); + } + + /** + * Create a new self-service profile. + * A token with {@code create:self_service_profiles} scope is needed + * @see https://auth0.com/docs/api/management/v2#!/self-service-profiles/post-self-service-profiles + * @param selfServiceProfile the self-service profile to create. + * @return a Request to execute. + */ + public Request create(SelfServiceProfile selfServiceProfile) { + Asserts.assertNotNull(selfServiceProfile, "self service profile"); + Asserts.assertNotNull(selfServiceProfile.getName(), "name"); + + String url = baseUrl.newBuilder() + .addPathSegments(ORGS_PATH) + .build() + .toString(); + + BaseRequest request = new BaseRequest<>(this.client, tokenProvider, url, HttpMethod.POST, new TypeReference() { + }); + request.setBody(selfServiceProfile); + return request; + } + + /** + * Request the self-service profile with the given ID. + * A token with {@code read:self_service_profiles} scope is needed + * @see https://auth0.com/docs/api/management/v2#!/self-service-profiles/get-self-service-profiles-by-id + * @param id the self-service profile ID. + * @return a Request to execute. + */ + public Request getById(String id) { + Asserts.assertNotNull(id, "id"); + + String url = baseUrl.newBuilder() + .addPathSegments(ORGS_PATH) + .addPathSegment(id) + .build() + .toString(); + + return new BaseRequest<>(this.client, tokenProvider, url, HttpMethod.GET, new TypeReference() { + }); + } + + /** + * Delete the self-service profile with the given ID. + * A token with {@code delete:self_service_profiles} scope is needed + * @see https://auth0.com/docs/api/management/v2#!/self-service-profiles/delete-self-service-profiles-by-id + * @param id the self-service profile ID. + * @return a Request to execute. + */ + public Request delete(String id) { + Asserts.assertNotNull(id, "id"); + + String url = baseUrl.newBuilder() + .addPathSegments(ORGS_PATH) + .addPathSegment(id) + .build() + .toString(); + + return new VoidRequest(this.client, tokenProvider, url, HttpMethod.DELETE); + } + + /** + * Update the self-service profile with the given ID. + * A token with {@code update:self_service_profiles} scope is needed + * @see https://auth0.com/docs/api/management/v2#!/self-service-profiles/patch-self-service-profiles-by-id + * @param selfServiceProfile the self-service profile to update. + * @param id the self-service profile ID. + * @return a Request to execute. + */ + public Request update(SelfServiceProfile selfServiceProfile, String id) { + Asserts.assertNotNull(selfServiceProfile, "self service profile"); + Asserts.assertNotNull(id, "id"); + + String url = baseUrl.newBuilder() + .addPathSegments(ORGS_PATH) + .addPathSegment(id) + .build() + .toString(); + + BaseRequest request = new BaseRequest<>(this.client, tokenProvider, url, HttpMethod.PATCH, new TypeReference() { + }); + request.setBody(selfServiceProfile); + return request; + } + + /** + * Get the custom text for specific self-service profile and language. + * A token with {@code read:self_service_profile_custom_texts} scope is needed + * @see https://auth0.com/docs/api/management/v2#!/self-service-profiles/get-self-service-profile-custom-text + * @param id the self-service profile ID. + * @param language the language. + * @param page the page. + * @return a Request to execute. + */ + public Request getCustomText(String id, String language, String page) { + Asserts.assertNotNull(id, "id"); + Asserts.assertNotNull(language, "language"); + Asserts.assertNotNull(page, "page"); + + HttpUrl.Builder builder = baseUrl.newBuilder() + .addPathSegments(ORGS_PATH) + .addPathSegment(id) + .addPathSegment("custom-text") + .addPathSegment(language) + .addPathSegment(page); + + String url = builder.build().toString(); + + return new BaseRequest<>(this.client, tokenProvider, url, HttpMethod.GET, new TypeReference() { + }); + } + + /** + * Set the custom text for specific self-service profile and language. + * A token with {@code update:self_service_profile_custom_texts} scope is needed + * @see https://auth0.com/docs/api/management/v2#!/self-service-profiles/put-self-service-profile-custom-text + * @param id the self-service profile ID. + * @param language the language. + * @param page the page. + * @param customText the custom text. + * @return a Request to execute. + */ + public Request setCustomText(String id, String language, String page, Object customText) { + Asserts.assertNotNull(id, "id"); + Asserts.assertNotNull(language, "language"); + Asserts.assertNotNull(page, "page"); + Asserts.assertNotNull(customText, "custom text"); + + HttpUrl.Builder builder = baseUrl.newBuilder() + .addPathSegments(ORGS_PATH) + .addPathSegment(id) + .addPathSegment("custom-text") + .addPathSegment(language) + .addPathSegment(page); + + String url = builder.build().toString(); + + BaseRequest request = new BaseRequest<>(this.client, tokenProvider, url, HttpMethod.PUT, new TypeReference() { + }); + request.setBody(customText); + return request; + } + + /** + * Create a new SSO access ticket. + * A token with {@code create:sso_access_tickets} scope is needed + * @see https://auth0.com/docs/api/management/v2#!/self-service-profiles/post-sso-ticket + * @param id the self-service profile ID. + * @param requestBody the payload. + * @return a Request to execute. + */ + public Request createSsoAccessTicket(String id, SsoAccessTicketRequest requestBody) { + Asserts.assertNotNull(id, "id"); + Asserts.assertNotNull(requestBody, "request body"); + + HttpUrl.Builder builder = baseUrl.newBuilder() + .addPathSegments(ORGS_PATH) + .addPathSegment(id) + .addPathSegment("sso-ticket"); + + String url = builder.build().toString(); + + BaseRequest request = new BaseRequest<>(this.client, tokenProvider, url, HttpMethod.POST, new TypeReference() { + }); + request.setBody(requestBody); + return request; + } + + + /** + * Create a new SSO access ticket. + * A token with {@code create:sso_access_tickets} scope is needed + * @see https://auth0.com/docs/api/management/v2#!/self-service-profiles/post-sso-ticket + * @param id the self-service profile ID. + * @param payload the payload. + * @return a Request to execute. + * + * @deprecated Use {@link #createSsoAccessTicket(String, SsoAccessTicketRequest)} to create sso access ticket. + */ + @Deprecated + public Request createSsoAccessTicket(String id, Object payload) { + Asserts.assertNotNull(id, "id"); + Asserts.assertNotNull(payload, "payload"); + + HttpUrl.Builder builder = baseUrl.newBuilder() + .addPathSegments(ORGS_PATH) + .addPathSegment(id) + .addPathSegment("sso-ticket"); + String url = builder.build().toString(); + + BaseRequest request = new BaseRequest<>(this.client, tokenProvider, url, HttpMethod.POST, new TypeReference() { + }); + request.setBody(payload); + return request; + } + + /** + * Revoke an SSO ticket. + * A token with {@code delete:sso_access_tickets} scope is needed + * @see https://auth0.com/docs/api/management/v2#!/self-service-profiles/post-revoke + * @param id the self-service profile ID. + * @param ticketId the ticket ID. + * @return a Request to execute. + */ + public Request revokeSsoTicket(String id, String ticketId) { + Asserts.assertNotNull(id, "id"); + Asserts.assertNotNull(ticketId, "ticket id"); + + HttpUrl.Builder builder = baseUrl.newBuilder() + .addPathSegments(ORGS_PATH) + .addPathSegment(id) + .addPathSegment("sso-ticket") + .addPathSegment(ticketId) + .addPathSegment("revoke"); + + String url = builder.build().toString(); + + return new EmptyBodyVoidRequest<>(this.client, tokenProvider, url, HttpMethod.POST, new TypeReference() { + }); + } +} diff --git a/src/main/java/com/auth0/client/mgmt/SessionsEntity.java b/src/main/java/com/auth0/client/mgmt/SessionsEntity.java new file mode 100644 index 000000000..ae701dac9 --- /dev/null +++ b/src/main/java/com/auth0/client/mgmt/SessionsEntity.java @@ -0,0 +1,89 @@ +package com.auth0.client.mgmt; + +import com.auth0.json.mgmt.sessions.Session; +import com.auth0.net.BaseRequest; +import com.auth0.net.EmptyBodyVoidRequest; +import com.auth0.net.Request; +import com.auth0.net.VoidRequest; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.HttpMethod; +import com.auth0.utils.Asserts; +import com.fasterxml.jackson.core.type.TypeReference; +import okhttp3.HttpUrl; + + +/** + * Class that provides an implementation of the Sessions methods of the Management API as defined in https://auth0.com/docs/api/management/v2#!/Sessions + *

+ * This class is not thread-safe. + * @see ManagementAPI + */ +@SuppressWarnings("WeakerAccess") +public class SessionsEntity extends BaseManagementEntity{ + + SessionsEntity(Auth0HttpClient client, HttpUrl baseUrl, TokenProvider tokenProvider) { + super(client, baseUrl, tokenProvider); + } + + /** + * Request the session for a given session ID. + * A token with scope {@code read:sessions} is needed. + * See https://auth0.com/docs/api/management/v2/sessions/get-session + * @param sessionId the session ID. + * @return a Request to execute. + */ + public Request get(String sessionId){ + Asserts.assertNotNull(sessionId, "session ID"); + + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/sessions") + .addPathSegment(sessionId) + .build() + .toString(); + + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { + }); + } + + /** + * Delete the session for a given session ID. + * A token with scope {@code delete:sessions} is needed. + * See https://auth0.com/docs/api/management/v2/sessions/delete-session + * @param sessionId the session ID. + * @return a Request to execute. + */ + public Request delete(String sessionId){ + Asserts.assertNotNull(sessionId, "session ID"); + + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/sessions") + .addPathSegment(sessionId) + .build() + .toString(); + + return new VoidRequest(client, tokenProvider, url, HttpMethod.DELETE); + } + + /** + * Revoke the session for a given session ID. + * A token with scope {@code delete:sessions}, {@code delete:refresh_tokens} is needed. + * See https://auth0.com/docs/api/management/v2/sessions/revoke-session + * @param sessionId the session ID. + * @return a Request to execute. + */ + public Request revoke(String sessionId){ + Asserts.assertNotNull(sessionId, "session ID"); + + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/sessions") + .addPathSegment(sessionId) + .addPathSegment("revoke") + .build() + .toString(); + + return new EmptyBodyVoidRequest<>(client, tokenProvider, url, HttpMethod.POST, new TypeReference() {}); + } +} diff --git a/src/main/java/com/auth0/client/mgmt/SimpleTokenProvider.java b/src/main/java/com/auth0/client/mgmt/SimpleTokenProvider.java new file mode 100644 index 000000000..d398ee429 --- /dev/null +++ b/src/main/java/com/auth0/client/mgmt/SimpleTokenProvider.java @@ -0,0 +1,33 @@ +package com.auth0.client.mgmt; + +import com.auth0.utils.Asserts; + +import java.util.concurrent.CompletableFuture; + +/** + * An implementation of {@link TokenProvider} that simply returns the token it is configured with. Tokens will not be renewed; + * consumers are responsible for renewing the token when needed and then calling {@link ManagementAPI#setApiToken(String)} with the + * new token. + */ +public class SimpleTokenProvider implements TokenProvider { + private final String apiToken; + + public static SimpleTokenProvider create(String apiToken) { + return new SimpleTokenProvider(apiToken); + } + + @Override + public String getToken() { + return apiToken; + } + + @Override + public CompletableFuture getTokenAsync() { + return CompletableFuture.supplyAsync(() -> apiToken); + } + + private SimpleTokenProvider(String apiToken) { + Asserts.assertNotNull(apiToken, "api token"); + this.apiToken = apiToken; + } +} diff --git a/src/main/java/com/auth0/client/mgmt/StatsEntity.java b/src/main/java/com/auth0/client/mgmt/StatsEntity.java index a1833c701..193e82468 100644 --- a/src/main/java/com/auth0/client/mgmt/StatsEntity.java +++ b/src/main/java/com/auth0/client/mgmt/StatsEntity.java @@ -1,12 +1,13 @@ package com.auth0.client.mgmt; -import com.auth0.json.mgmt.DailyStats; -import com.auth0.net.CustomRequest; +import com.auth0.json.mgmt.stats.DailyStats; +import com.auth0.net.BaseRequest; import com.auth0.net.Request; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.HttpMethod; import com.auth0.utils.Asserts; import com.fasterxml.jackson.core.type.TypeReference; import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; import java.text.SimpleDateFormat; import java.util.Date; @@ -22,8 +23,8 @@ @SuppressWarnings("WeakerAccess") public class StatsEntity extends BaseManagementEntity { - StatsEntity(OkHttpClient client, HttpUrl baseUrl, String apiToken) { - super(client, baseUrl, apiToken); + StatsEntity(Auth0HttpClient client, HttpUrl baseUrl, TokenProvider tokenProvider) { + super(client, baseUrl, tokenProvider); } /** @@ -39,10 +40,8 @@ public Request getActiveUsersCount() { .build() .toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", new TypeReference() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; } /** @@ -67,10 +66,8 @@ public Request> getDailyStats(Date from, Date to) { .build() .toString(); - CustomRequest> request = new CustomRequest<>(client, url, "GET", new TypeReference>() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference>() { }); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; } protected String formatDate(Date date) { diff --git a/src/main/java/com/auth0/client/mgmt/TenantsEntity.java b/src/main/java/com/auth0/client/mgmt/TenantsEntity.java index fe439eb71..af6c790cf 100644 --- a/src/main/java/com/auth0/client/mgmt/TenantsEntity.java +++ b/src/main/java/com/auth0/client/mgmt/TenantsEntity.java @@ -2,12 +2,13 @@ import com.auth0.client.mgmt.filter.FieldsFilter; import com.auth0.json.mgmt.tenants.Tenant; -import com.auth0.net.CustomRequest; +import com.auth0.net.BaseRequest; import com.auth0.net.Request; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.HttpMethod; import com.auth0.utils.Asserts; import com.fasterxml.jackson.core.type.TypeReference; import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; import java.util.Map; @@ -21,8 +22,8 @@ @SuppressWarnings("WeakerAccess") public class TenantsEntity extends BaseManagementEntity { - TenantsEntity(OkHttpClient client, HttpUrl baseUrl, String apiToken) { - super(client, baseUrl, apiToken); + TenantsEntity(Auth0HttpClient client, HttpUrl baseUrl, TokenProvider tokenProvider) { + super(client, baseUrl, tokenProvider); } /** @@ -42,10 +43,8 @@ public Request get(FieldsFilter filter) { } } String url = builder.build().toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", new TypeReference() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; } /** @@ -64,9 +63,8 @@ public Request update(Tenant tenant) { .build() .toString(); - CustomRequest request = new CustomRequest<>(client, url, "PATCH", new TypeReference() { + BaseRequest request = new BaseRequest<>(client, tokenProvider, url, HttpMethod.PATCH, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); request.setBody(tenant); return request; } diff --git a/src/main/java/com/auth0/client/mgmt/TicketsEntity.java b/src/main/java/com/auth0/client/mgmt/TicketsEntity.java index 5b03e148b..698a8787b 100644 --- a/src/main/java/com/auth0/client/mgmt/TicketsEntity.java +++ b/src/main/java/com/auth0/client/mgmt/TicketsEntity.java @@ -2,12 +2,13 @@ import com.auth0.json.mgmt.tickets.EmailVerificationTicket; import com.auth0.json.mgmt.tickets.PasswordChangeTicket; -import com.auth0.net.CustomRequest; +import com.auth0.net.BaseRequest; import com.auth0.net.Request; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.HttpMethod; import com.auth0.utils.Asserts; import com.fasterxml.jackson.core.type.TypeReference; import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; /** * Class that provides an implementation of the Tickets methods of the Management API as defined in https://auth0.com/docs/api/management/v2#!/Tickets @@ -19,8 +20,8 @@ @SuppressWarnings("WeakerAccess") public class TicketsEntity extends BaseManagementEntity { - TicketsEntity(OkHttpClient client, HttpUrl baseUrl, String apiToken) { - super(client, baseUrl, apiToken); + TicketsEntity(Auth0HttpClient client, HttpUrl baseUrl, TokenProvider tokenProvider) { + super(client, baseUrl, tokenProvider); } /** @@ -39,9 +40,8 @@ public Request requestEmailVerification(EmailVerificati .build() .toString(); - CustomRequest request = new CustomRequest<>(client, url, "POST", new TypeReference() { + BaseRequest request = new BaseRequest<>(client, tokenProvider, url, HttpMethod.POST, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); request.setBody(emailVerificationTicket); return request; } @@ -62,9 +62,8 @@ public Request requestPasswordChange(PasswordChangeTicket .build() .toString(); - CustomRequest request = new CustomRequest<>(client, url, "POST", new TypeReference() { + BaseRequest request = new BaseRequest<>(client, tokenProvider, url, HttpMethod.POST, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); request.setBody(passwordChangeTicket); return request; } diff --git a/src/main/java/com/auth0/client/mgmt/TokenProvider.java b/src/main/java/com/auth0/client/mgmt/TokenProvider.java new file mode 100644 index 000000000..63c1b98c6 --- /dev/null +++ b/src/main/java/com/auth0/client/mgmt/TokenProvider.java @@ -0,0 +1,25 @@ +package com.auth0.client.mgmt; + +import com.auth0.exception.Auth0Exception; + +import java.util.concurrent.CompletableFuture; + +/** + * A {@code TokenProvider} is responsible for providing the token used when making authorized requests to the Auth0 + * Management API. + */ +public interface TokenProvider { + + /** + * Responsible for obtaining a token for use with the {@link ManagementAPI} client for synchronous requests. + * @return the token required when making requests to the Auth0 Management API. + * @throws Auth0Exception if the token cannot be retrieved. + */ + String getToken() throws Auth0Exception; + + /** + * Responsible for obtaining a token for use with the {@link ManagementAPI} client for asynchronous requests. + * @return a {@link CompletableFuture} with the token required when making requests to the Auth0 Management API. + */ + CompletableFuture getTokenAsync(); +} diff --git a/src/main/java/com/auth0/client/mgmt/UserAttributeProfilesEntity.java b/src/main/java/com/auth0/client/mgmt/UserAttributeProfilesEntity.java new file mode 100644 index 000000000..053f89877 --- /dev/null +++ b/src/main/java/com/auth0/client/mgmt/UserAttributeProfilesEntity.java @@ -0,0 +1,151 @@ +package com.auth0.client.mgmt; + +import com.auth0.client.mgmt.filter.UserAttributeProfilesFilter; +import com.auth0.json.mgmt.userAttributeProfiles.*; +import com.auth0.net.BaseRequest; +import com.auth0.net.Request; +import com.auth0.net.VoidRequest; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.HttpMethod; +import com.auth0.utils.Asserts; +import com.fasterxml.jackson.core.type.TypeReference; +import okhttp3.HttpUrl; + +public class UserAttributeProfilesEntity extends BaseManagementEntity { + + private final static String ORGS_PATH = "api/v2/user-attribute-profiles"; + + UserAttributeProfilesEntity(Auth0HttpClient client, HttpUrl baseUrl, TokenProvider tokenProvider) { + super(client, baseUrl, tokenProvider); + } + + /** + * Get a user attribute profile by its ID. A token with {@code read:user_attribute_profiles} scope is required. + * @param id the ID of the user attribute profile to retrieve. + * @return a Request to execute. + */ + public Request get(String id) { + Asserts.assertNotNull(id, "id"); + + String url = baseUrl.newBuilder() + .addPathSegments(ORGS_PATH) + .addPathSegment(id) + .build().toString(); + + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { + }); + } + + /** + * Get all user attribute profiles. A token with {@code read:user_attribute_profiles} scope is required. + * + * @param filter an optional pagination filter + * @return a Request to execute + * + */ + public Request getAll(UserAttributeProfilesFilter filter) { + HttpUrl.Builder builder = baseUrl.newBuilder() + .addPathSegments(ORGS_PATH); + + if (filter != null) { + filter.getAsMap().forEach((k, v) -> builder.addQueryParameter(k, String.valueOf(v))); + } + + String url = builder.build().toString(); + + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { + }); + } + + /** + * Update a user attribute profile. A token with {@code update:user_attribute_profiles} scope is required. + * + * @param userAttributeProfile the user attribute profile to update. + * @return a Request to execute. + */ + public Request update(String id, UserAttributeProfile userAttributeProfile) { + Asserts.assertNotNull(id, "id"); + Asserts.assertNotNull(userAttributeProfile, "userAttributeProfile"); + + String url = baseUrl.newBuilder() + .addPathSegments(ORGS_PATH) + .addPathSegment(id) + .build().toString(); + + BaseRequest request = new BaseRequest<>(client, tokenProvider, url, HttpMethod.PATCH, new TypeReference() { + }); + + request.setBody(userAttributeProfile); + return request; + } + + /** + * Create a new user attribute profile. A token with {@code create:user_attribute_profiles} scope is required. + * @param userAttributeProfile the user attribute profile to create. + * @return a Request to execute. + */ + public Request create(UserAttributeProfile userAttributeProfile) { + Asserts.assertNotNull(userAttributeProfile.getName(), "name"); + Asserts.assertNotNull(userAttributeProfile.getUserAttributes(), "userAttributes"); + + String url = baseUrl.newBuilder() + .addPathSegments(ORGS_PATH) + .build().toString(); + + BaseRequest request = new BaseRequest<>(client, tokenProvider, url, HttpMethod.POST, new TypeReference() { + }); + + request.setBody(userAttributeProfile); + return request; + } + + /** + * Delete a user attribute profile by its ID. A token with {@code delete:user_attribute_profiles} scope is required. + * @param id the ID of the user attribute profile to delete. + * @return a Request to execute. + */ + public Request delete(String id) { + Asserts.assertNotNull(id, "id"); + + HttpUrl.Builder builder = baseUrl + .newBuilder() + .addPathSegments(ORGS_PATH) + .addPathSegment(id); + + String url = builder.build().toString(); + return new VoidRequest(client, tokenProvider, url, HttpMethod.DELETE); + } + + /** + * Get a user attribute profile template by its ID. A token with {@code read:user_attribute_profiles} scope is required. + * @param id the ID of the user attribute profile template to retrieve. + * @return a Request to execute. + */ + public Request getTemplate(String id) { + Asserts.assertNotNull(id, "id"); + + String url = baseUrl.newBuilder() + .addPathSegments(ORGS_PATH) + .addPathSegment("templates") + .addPathSegment(id) + .build().toString(); + + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { + }); + } + + /** + * Get all user attribute profile templates. A token with {@code read:user_attribute_profiles} scope is required. + * + * @return a Request to execute + */ + public Request getAllTemplates() { + String url = baseUrl.newBuilder() + .addPathSegments(ORGS_PATH) + .addPathSegment("templates") + .build().toString(); + + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { + }); + } +} diff --git a/src/main/java/com/auth0/client/mgmt/UserBlocksEntity.java b/src/main/java/com/auth0/client/mgmt/UserBlocksEntity.java index 806d3b691..d85260942 100644 --- a/src/main/java/com/auth0/client/mgmt/UserBlocksEntity.java +++ b/src/main/java/com/auth0/client/mgmt/UserBlocksEntity.java @@ -1,13 +1,14 @@ package com.auth0.client.mgmt; import com.auth0.json.mgmt.userblocks.UserBlocks; -import com.auth0.net.CustomRequest; +import com.auth0.net.BaseRequest; import com.auth0.net.Request; import com.auth0.net.VoidRequest; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.HttpMethod; import com.auth0.utils.Asserts; import com.fasterxml.jackson.core.type.TypeReference; import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; /** * Class that provides an implementation of the User Blocks methods of the Management API as defined in https://auth0.com/docs/api/management/v2#!/User_Blocks @@ -19,8 +20,8 @@ @SuppressWarnings("WeakerAccess") public class UserBlocksEntity extends BaseManagementEntity { - UserBlocksEntity(OkHttpClient client, HttpUrl baseUrl, String apiToken) { - super(client, baseUrl, apiToken); + UserBlocksEntity(Auth0HttpClient client, HttpUrl baseUrl, TokenProvider tokenProvider) { + super(client, baseUrl, tokenProvider); } /** @@ -39,10 +40,8 @@ public Request getByIdentifier(String identifier) { .addQueryParameter("identifier", identifier) .build() .toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", new TypeReference() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; } /** @@ -61,9 +60,7 @@ public Request deleteByIdentifier(String identifier) { .addQueryParameter("identifier", identifier) .build() .toString(); - VoidRequest request = new VoidRequest(client, url, "DELETE"); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; + return new VoidRequest(client, tokenProvider, url, HttpMethod.DELETE); } /** @@ -82,10 +79,8 @@ public Request get(String userId) { .addPathSegment(userId) .build() .toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", new TypeReference() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; } /** @@ -104,8 +99,6 @@ public Request delete(String userId) { .addPathSegment(userId) .build() .toString(); - VoidRequest request = new VoidRequest(client, url, "DELETE"); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; + return new VoidRequest(client, tokenProvider, url, HttpMethod.DELETE); } } diff --git a/src/main/java/com/auth0/client/mgmt/UsersEntity.java b/src/main/java/com/auth0/client/mgmt/UsersEntity.java index b216476a5..66b00e616 100644 --- a/src/main/java/com/auth0/client/mgmt/UsersEntity.java +++ b/src/main/java/com/auth0/client/mgmt/UsersEntity.java @@ -1,9 +1,11 @@ package com.auth0.client.mgmt; import com.auth0.client.mgmt.filter.*; -import com.auth0.json.mgmt.Permission; -import com.auth0.json.mgmt.PermissionsPage; -import com.auth0.json.mgmt.RolesPage; +import com.auth0.json.mgmt.users.authenticationmethods.AuthenticationMethod; +import com.auth0.json.mgmt.users.authenticationmethods.AuthenticationMethodsPage; +import com.auth0.json.mgmt.permissions.Permission; +import com.auth0.json.mgmt.permissions.PermissionsPage; +import com.auth0.json.mgmt.roles.RolesPage; import com.auth0.json.mgmt.guardian.Enrollment; import com.auth0.json.mgmt.logevents.LogEventsPage; import com.auth0.json.mgmt.organizations.OrganizationsPage; @@ -11,14 +13,17 @@ import com.auth0.json.mgmt.users.RecoveryCode; import com.auth0.json.mgmt.users.User; import com.auth0.json.mgmt.users.UsersPage; -import com.auth0.net.CustomRequest; +import com.auth0.json.mgmt.refreshtokens.RefreshTokensPage; +import com.auth0.json.mgmt.sessions.SessionsPage; import com.auth0.net.EmptyBodyRequest; +import com.auth0.net.BaseRequest; import com.auth0.net.Request; import com.auth0.net.VoidRequest; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.HttpMethod; import com.auth0.utils.Asserts; import com.fasterxml.jackson.core.type.TypeReference; import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; import java.util.HashMap; import java.util.List; @@ -36,8 +41,8 @@ @SuppressWarnings("WeakerAccess") public class UsersEntity extends BaseManagementEntity { - UsersEntity(OkHttpClient client, HttpUrl baseUrl, String apiToken) { - super(client, baseUrl, apiToken); + UsersEntity(Auth0HttpClient client, HttpUrl baseUrl, TokenProvider tokenProvider) { + super(client, baseUrl, tokenProvider); } /** @@ -64,10 +69,8 @@ public Request> listByEmail(String email, FieldsFilter filter) { } String url = builder.build().toString(); - CustomRequest> request = new CustomRequest<>(client, url, "GET", new TypeReference>() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference>() { }); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; } /** @@ -85,10 +88,8 @@ public Request list(UserFilter filter) { .addPathSegments("api/v2/users"); encodeAndAddQueryParam(builder, filter); String url = builder.build().toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", new TypeReference() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; } /** @@ -114,10 +115,8 @@ public Request get(String userId, UserFilter filter) { } } String url = builder.build().toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", new TypeReference() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; } /** @@ -136,9 +135,8 @@ public Request create(User user) { .addPathSegments("api/v2/users") .build() .toString(); - CustomRequest request = new CustomRequest<>(this.client, url, "POST", new TypeReference() { + BaseRequest request = new BaseRequest<>(this.client, tokenProvider, url, HttpMethod.POST, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); request.setBody(user); return request; } @@ -160,9 +158,7 @@ public Request delete(String userId) { .addPathSegment(userId) .build() .toString(); - VoidRequest request = new VoidRequest(client, url, "DELETE"); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; + return new VoidRequest(client, tokenProvider, url, HttpMethod.DELETE); } /** @@ -185,9 +181,8 @@ public Request update(String userId, User user) { .addPathSegment(userId) .build() .toString(); - CustomRequest request = new CustomRequest<>(this.client, url, "PATCH", new TypeReference() { + BaseRequest request = new BaseRequest<>(this.client, tokenProvider, url, HttpMethod.PATCH, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); request.setBody(user); return request; } @@ -211,10 +206,8 @@ public Request> getEnrollments(String userId) { .build() .toString(); - CustomRequest> request = new CustomRequest<>(client, url, "GET", new TypeReference>() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference>() { }); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; } /** @@ -237,12 +230,33 @@ public Request getLogEvents(String userId, LogEventFilter filter) encodeAndAddQueryParam(builder, filter); String url = builder.build().toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", new TypeReference() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; } + /** + * Delete all an user's authenticators. + * A token with scope delete:guardian_enrollments is needed. + * + * See API docs + * + * @param userId the user id + * @return a Request to execute. + */ + public Request deleteAllAuthenticators(String userId) { + + Asserts.assertNotNull(userId, "user id"); + + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/users") + .addPathSegment(userId) + .addPathSegment("authenticators") + .build() + .toString(); + return new VoidRequest(client, tokenProvider, url, HttpMethod.DELETE); + } + /** * Delete an existing User's Multifactor Provider. * A token with scope update:users is needed. @@ -264,9 +278,7 @@ public Request deleteMultifactorProvider(String userId, String provider) { .addPathSegment(provider) .build() .toString(); - VoidRequest request = new VoidRequest(client, url, "DELETE"); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; + return new VoidRequest(client, tokenProvider, url, HttpMethod.DELETE); } /** @@ -288,10 +300,8 @@ public Request rotateRecoveryCode(String userId) { .build() .toString(); - EmptyBodyRequest request = new EmptyBodyRequest<>(client, url, "POST", new TypeReference() { + return new EmptyBodyRequest<>(client, tokenProvider, url, HttpMethod.POST, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; } /** @@ -318,9 +328,8 @@ public Request> linkIdentity(String primaryUserId, String seconda .build() .toString(); - CustomRequest> request = new CustomRequest<>(client, url, "POST", new TypeReference>() { + BaseRequest> request = new BaseRequest<>(client, tokenProvider, url, HttpMethod.POST, new TypeReference>() { }); - request.addHeader("Authorization", "Bearer " + apiToken); request.addParameter("provider", provider); request.addParameter("user_id", secondaryUserId); if (connectionId != null) { @@ -350,9 +359,8 @@ public Request> linkIdentity(String primaryUserId, String seconda .build() .toString(); - CustomRequest> request = new CustomRequest<>(client, url, "POST", new TypeReference>() { + BaseRequest> request = new BaseRequest<>(client, tokenProvider, url, HttpMethod.POST, new TypeReference>() { }); - request.addHeader("Authorization", "Bearer " + apiToken); request.addParameter("link_with", secondaryIdToken); return request; @@ -383,9 +391,30 @@ public Request> unlinkIdentity(String primaryUserId, String secon .build() .toString(); - CustomRequest> request = new CustomRequest<>(client, url, "DELETE", new TypeReference>() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.DELETE, new TypeReference>() { }); - request.addHeader("Authorization", "Bearer " + apiToken); + } + + /** + * Invalidate all remembered browsers across all authentication factors for a user. + * A token with scope {@code update:users} is required. + * + * @param userId the ID of the user to invalidate all remembered browsers and authentication factors for. + * @see Invalidate all remembered browsers. + */ + public Request invalidateRememberedBrowsers(String userId) { + Asserts.assertNotNull(userId, "user ID"); + + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/users") + .addPathSegment(userId) + .addPathSegments("multifactor/actions/invalidate-remember-browser") + .build() + .toString(); + + VoidRequest request = new VoidRequest(client, tokenProvider, url, HttpMethod.POST); + request.setBody(""); return request; } @@ -403,18 +432,16 @@ public Request listPermissions(String userId, PageFilter filter HttpUrl.Builder builder = baseUrl .newBuilder() .addPathSegments("api/v2/users") - .addPathSegments(userId) - .addPathSegments("permissions"); + .addPathSegment(userId) + .addPathSegment("permissions"); if (filter != null) { for (Map.Entry e : filter.getAsMap().entrySet()) { builder.addQueryParameter(e.getKey(), String.valueOf(e.getValue())); } } String url = builder.build().toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", new TypeReference() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; } @@ -437,13 +464,12 @@ public Request removePermissions(String userId, List permissio final String url = baseUrl .newBuilder() .addPathSegments("api/v2/users") - .addPathSegments(userId) - .addPathSegments("permissions") + .addPathSegment(userId) + .addPathSegment("permissions") .build() .toString(); - VoidRequest request = new VoidRequest(this.client, url, "DELETE"); + VoidRequest request = new VoidRequest(this.client, tokenProvider, url, HttpMethod.DELETE); request.setBody(body); - request.addHeader("Authorization", "Bearer " + apiToken); return request; } @@ -466,13 +492,12 @@ public Request addPermissions(String userId, List permissions) final String url = baseUrl .newBuilder() .addPathSegments("api/v2/users") - .addPathSegments(userId) - .addPathSegments("permissions") + .addPathSegment(userId) + .addPathSegment("permissions") .build() .toString(); - VoidRequest request = new VoidRequest(this.client, url, "POST"); + VoidRequest request = new VoidRequest(this.client, tokenProvider, url, HttpMethod.POST); request.setBody(body); - request.addHeader("Authorization", "Bearer " + apiToken); return request; } @@ -490,18 +515,16 @@ public Request listRoles(String userId, PageFilter filter) { HttpUrl.Builder builder = baseUrl .newBuilder() .addPathSegments("api/v2/users") - .addPathSegments(userId) - .addPathSegments("roles"); + .addPathSegment(userId) + .addPathSegment("roles"); if (filter != null) { for (Map.Entry e : filter.getAsMap().entrySet()) { builder.addQueryParameter(e.getKey(), String.valueOf(e.getValue())); } } String url = builder.build().toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", new TypeReference() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); - return request; } @@ -524,13 +547,12 @@ public Request removeRoles(String userId, List roleIds) { final String url = baseUrl .newBuilder() .addPathSegments("api/v2/users") - .addPathSegments(userId) - .addPathSegments("roles") + .addPathSegment(userId) + .addPathSegment("roles") .build() .toString(); - VoidRequest request = new VoidRequest(this.client, url, "DELETE"); + VoidRequest request = new VoidRequest(this.client, tokenProvider, url, HttpMethod.DELETE); request.setBody(body); - request.addHeader("Authorization", "Bearer " + apiToken); return request; } @@ -553,13 +575,12 @@ public Request addRoles(String userId, List roleIds) { final String url = baseUrl .newBuilder() .addPathSegments("api/v2/users") - .addPathSegments(userId) - .addPathSegments("roles") + .addPathSegment(userId) + .addPathSegment("roles") .build() .toString(); - VoidRequest request = new VoidRequest(this.client, url, "POST"); + VoidRequest request = new VoidRequest(this.client, tokenProvider, url, HttpMethod.POST); request.setBody(body); - request.addHeader("Authorization", "Bearer " + apiToken); return request; } @@ -588,12 +609,291 @@ public Request getOrganizations(String userId, PageFilter fil } } String url = builder.build().toString(); - CustomRequest request = new CustomRequest<>(client, url, "GET", new TypeReference() { + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { + }); + } + + /** + * Get the authentication methods of the user. + * A token with {@code read:authentication_methods} is required. + * + * @param userId the user ID + * @param filter an optional pagination filter + * @return a Request to execute + * + * @see https://auth0.com/docs/api/management/v2#!/Users/get_authentication_methods + */ + public Request getAuthenticationMethods(String userId, PageFilter filter) { + Asserts.assertNotNull(userId, "user ID"); + + HttpUrl.Builder builder = baseUrl + .newBuilder() + .addPathSegments("api/v2/users") + .addPathSegment(userId) + .addPathSegment("authentication-methods"); + + if (filter != null) { + for (Map.Entry e : filter.getAsMap().entrySet()) { + builder.addQueryParameter(e.getKey(), String.valueOf(e.getValue())); + } + } + String url = builder.build().toString(); + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { + }); + } + + /** + * Create an authentication method for a given user. + * A token with scope {@code create:authentication_methods} is needed. + * @see https://auth0.com/docs/api/management/v2#!/Users/post_authentication_methods + * + * @param userId the user to add authentication method to + * @param authenticationMethod the authentication method to be created + * @return a Request to execute. + */ + public Request createAuthenticationMethods(String userId, AuthenticationMethod authenticationMethod) { + Asserts.assertNotNull(userId, "user ID"); + Asserts.assertNotNull(authenticationMethod, "authentication methods"); + + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/users") + .addPathSegment(userId) + .addPathSegment("authentication-methods") + .build() + .toString(); + BaseRequest request = new BaseRequest<>(this.client, tokenProvider, url, HttpMethod.POST, new TypeReference() { + }); + request.setBody(authenticationMethod); + return request; + } + + /** + * Updates an authentication method for a given user. + * A token with scope {@code update:authentication_methods} is needed. + * @see https://auth0.com/docs/api/management/v2#!/Users/put_authentication_methods + * + * @param userId the user to update authentication method + * @param authenticationMethods the list of authentication method information to be updated + * @return a Request to execute. + */ + public Request> updateAuthenticationMethods(String userId, List authenticationMethods) { + Asserts.assertNotNull(userId, "user ID"); + Asserts.assertNotNull(authenticationMethods, "authentication methods"); + + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/users") + .addPathSegment(userId) + .addPathSegment("authentication-methods") + .build() + .toString(); + BaseRequest> request = new BaseRequest<>(this.client, tokenProvider, url, HttpMethod.PUT, new TypeReference>() { + }); + request.setBody(authenticationMethods); + return request; + } + + /** + * Gets an authentication method by ID. + * A token with scope {@code read:authentication_methods} is needed. + * @see https://auth0.com/docs/api/management/v2#!/Users/get_authentication_methods_by_authentication_method_id + * + * @param userId the user to get authentication method for + * @param authenticationMethodId the authentication method to be fetched + * @return a Request to execute. + */ + public Request getAuthenticationMethodById(String userId, String authenticationMethodId) { + Asserts.assertNotNull(userId, "user ID"); + Asserts.assertNotNull(authenticationMethodId, "authentication method ID"); + + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/users") + .addPathSegment(userId) + .addPathSegment("authentication-methods") + .addPathSegment(authenticationMethodId) + .build() + .toString(); + + return new BaseRequest<>(this.client, tokenProvider, url, HttpMethod.GET, new TypeReference() { }); - request.addHeader("Authorization", "Bearer " + apiToken); + } + + /** + * Deletes an authentication method by ID. + * A token with scope {@code delete:authentication_methods} is needed. + * @see https://auth0.com/docs/api/management/v2#!/Users/delete_authentication_methods_by_authentication_method_id + * + * @param userId the user to delete the authentication method for + * @param authenticationMethodId the authentication method to be deleted + * @return a Request to execute. + */ + public Request deleteAuthenticationMethodById(String userId, String authenticationMethodId) { + Asserts.assertNotNull(userId, "user ID"); + Asserts.assertNotNull(authenticationMethodId, "authentication method ID"); + + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/users") + .addPathSegment(userId) + .addPathSegment("authentication-methods") + .addPathSegment(authenticationMethodId) + .build() + .toString(); + + return new VoidRequest(this.client, tokenProvider, url, HttpMethod.DELETE); + } + + /** + * Deletes all authentication methods for the given user. + * A token with scope {@code delete:authentication_methods} is needed. + * @see https://auth0.com/docs/api/management/v2/users/delete-authentication-methods + * + * @param userId the user to delete the authentication method for + * @return a Request to execute. + */ + public Request deleteAllAuthenticationMethods(String userId) { + Asserts.assertNotNull(userId, "user ID"); + + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/users") + .addPathSegment(userId) + .addPathSegment("authentication-methods") + .build() + .toString(); + + return new VoidRequest(this.client, tokenProvider, url, HttpMethod.DELETE); + } + + /** + * Updates an authentication method. + * A token with scope {@code update:authentication_methods} is needed. + * @see https://auth0.com/docs/api/management/v2#!/Users/patch_authentication_methods_by_authentication_method_id + * + * @param userId the user to delete the authentication method for + * @param authenticationMethodId the authentication method to be deleted + * @param authenticationMethod the information to be updated + * @return a Request to execute. + */ + public Request updateAuthenticationMethodById(String userId, String authenticationMethodId, AuthenticationMethod authenticationMethod) { + Asserts.assertNotNull(userId, "user ID"); + Asserts.assertNotNull(authenticationMethodId, "authentication method ID"); + Asserts.assertNotNull(authenticationMethod, "authentication method"); + + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/users") + .addPathSegment(userId) + .addPathSegment("authentication-methods") + .addPathSegment(authenticationMethodId) + .build() + .toString(); + + BaseRequest request = new BaseRequest<>(this.client, tokenProvider, url, HttpMethod.PATCH, new TypeReference() { + }); + request.setBody(authenticationMethod); return request; } + /** + * Get refresh tokens for a user + * A token with {@code read:refresh_tokens} is needed. + * See https://auth0.com/docs/api/management/v2/users/get-refresh-tokens-for-user + * + * @param userId the role id + * @param filter an optional pagination filter + * @return a Request to execute + */ + public Request listRefreshTokens(String userId, PageFilter filter) { + Asserts.assertNotNull(userId, "user ID"); + HttpUrl.Builder builder = baseUrl + .newBuilder() + .addPathSegments("api/v2/users") + .addPathSegment(userId) + .addPathSegment("refresh-tokens"); + if (filter != null) { + for (Map.Entry e : filter.getAsMap().entrySet()) { + builder.addQueryParameter(e.getKey(), String.valueOf(e.getValue())); + } + } + String url = builder.build().toString(); + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { + }); + } + + /** + * Delete all refresh tokens for a user. + * A token with scope {@code delete:refresh_tokens} is needed. + * See https://auth0.com/docs/api/management/v2/users/delete-refresh-tokens-for-user + * + * @param userId the user to delete the refresh tokens for + * @return a Request to execute. + */ + public Request deleteRefreshTokens(String userId) { + Asserts.assertNotNull(userId, "user ID"); + + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/users") + .addPathSegment(userId) + .addPathSegment("refresh-tokens") + .build() + .toString(); + + return new VoidRequest(this.client, tokenProvider, url, HttpMethod.DELETE); + } + + + /** + * Get sessions for user + * A token with {@code read:sessions} is needed. + * See https://auth0.com/docs/api/management/v2/users/get-sessions-for-user + * + * @param userId the role id + * @param filter an optional pagination filter + * @return a Request to execute + */ + public Request listSessions(String userId, PageFilter filter) { + Asserts.assertNotNull(userId, "user ID"); + HttpUrl.Builder builder = baseUrl + .newBuilder() + .addPathSegments("api/v2/users") + .addPathSegment(userId) + .addPathSegment("sessions"); + if (filter != null) { + for (Map.Entry e : filter.getAsMap().entrySet()) { + builder.addQueryParameter(e.getKey(), String.valueOf(e.getValue())); + } + } + String url = builder.build().toString(); + return new BaseRequest<>(client, tokenProvider, url, HttpMethod.GET, new TypeReference() { + }); + } + + /** + * Delete sessions for user + * A token with scope {@code delete:sessions} is needed. + * See https://auth0.com/docs/api/management/v2/users/delete-sessions-for-user + * + * @param userId the user to delete the sessions for + * @return a Request to execute. + */ + public Request deleteSessions(String userId) { + Asserts.assertNotNull(userId, "user ID"); + + String url = baseUrl + .newBuilder() + .addPathSegments("api/v2/users") + .addPathSegment(userId) + .addPathSegment("sessions") + .build() + .toString(); + + return new VoidRequest(this.client, tokenProvider, url, HttpMethod.DELETE); + } + private static void encodeAndAddQueryParam(HttpUrl.Builder builder, BaseFilter filter) { if (filter != null) { for (Map.Entry e : filter.getAsMap().entrySet()) { diff --git a/src/main/java/com/auth0/client/mgmt/filter/ClientFilter.java b/src/main/java/com/auth0/client/mgmt/filter/ClientFilter.java index 00e53e2f0..0ce98687b 100644 --- a/src/main/java/com/auth0/client/mgmt/filter/ClientFilter.java +++ b/src/main/java/com/auth0/client/mgmt/filter/ClientFilter.java @@ -71,4 +71,15 @@ public ClientFilter withFields(String fields, boolean includeFields) { super.withFields(fields, includeFields); return this; } + + /** + * Filter by custom query + * + * @param query the query string using Lucene query syntax + * @return this filter instance + */ + public ClientFilter withQuery(String query) { + parameters.put("q", query); + return this; + } } diff --git a/src/main/java/com/auth0/client/mgmt/filter/ClientGrantsFilter.java b/src/main/java/com/auth0/client/mgmt/filter/ClientGrantsFilter.java index 94f6ab399..15da9b9e3 100644 --- a/src/main/java/com/auth0/client/mgmt/filter/ClientGrantsFilter.java +++ b/src/main/java/com/auth0/client/mgmt/filter/ClientGrantsFilter.java @@ -31,6 +31,16 @@ public ClientGrantsFilter withAudience(String audience) { return this; } + /** + * Filter by {@code allow_any_organization} + * @param allowAnyOrganization only retrieve items with the {@code allow_any_organization} value specfied. + * @return this filter instance. + */ + public ClientGrantsFilter withAllowAnyOrganization(Boolean allowAnyOrganization) { + parameters.put("allow_any_organization", allowAnyOrganization); + return this; + } + /** * Filter by page * diff --git a/src/main/java/com/auth0/client/mgmt/filter/ConnectionFilter.java b/src/main/java/com/auth0/client/mgmt/filter/ConnectionFilter.java index 375fe13d7..d1a160f8f 100644 --- a/src/main/java/com/auth0/client/mgmt/filter/ConnectionFilter.java +++ b/src/main/java/com/auth0/client/mgmt/filter/ConnectionFilter.java @@ -61,4 +61,27 @@ public ConnectionFilter withFields(String fields, boolean includeFields) { super.withFields(fields, includeFields); return this; } + + /** + * Include the {@code from} parameter to specify where to start the page selection. Only applicable for endpoints that + * support checkpoint pagination. + * @param from the ID from which to start selection. This can be obtained from the {@code next} field returned from + * a checkpoint-paginated result. + * @return this filter instance. + */ + public ConnectionFilter withFrom(String from) { + parameters.put("from", from); + return this; + } + + /** + * Include the {@code take} parameter to specify the amount of results to return per page. Only applicable for endpoints that + * support checkpoint pagination. + * @param take the amount of entries to retrieve per page. + * @return this filter instance. + */ + public ConnectionFilter withTake(int take) { + parameters.put("take", take); + return this; + } } diff --git a/src/main/java/com/auth0/client/mgmt/filter/DeviceCredentialsFilter.java b/src/main/java/com/auth0/client/mgmt/filter/DeviceCredentialsFilter.java index b1c9ee909..1e3a96748 100644 --- a/src/main/java/com/auth0/client/mgmt/filter/DeviceCredentialsFilter.java +++ b/src/main/java/com/auth0/client/mgmt/filter/DeviceCredentialsFilter.java @@ -47,4 +47,28 @@ public DeviceCredentialsFilter withFields(String fields, boolean includeFields) super.withFields(fields, includeFields); return this; } + + /** + * Filter by page + * + * @param pageNumber the page number to retrieve. + * @param amountPerPage the amount of items per page to retrieve. + * @return this filter instance + */ + public DeviceCredentialsFilter withPage(int pageNumber, int amountPerPage) { + parameters.put("page", pageNumber); + parameters.put("per_page", amountPerPage); + return this; + } + + /** + * Include the query summary + * + * @param includeTotals whether to include or not the query summary. + * @return this filter instance + */ + public DeviceCredentialsFilter withTotals(boolean includeTotals) { + parameters.put("include_totals", includeTotals); + return this; + } } diff --git a/src/main/java/com/auth0/client/mgmt/filter/EnabledClientsFilter.java b/src/main/java/com/auth0/client/mgmt/filter/EnabledClientsFilter.java new file mode 100644 index 000000000..65cea8a04 --- /dev/null +++ b/src/main/java/com/auth0/client/mgmt/filter/EnabledClientsFilter.java @@ -0,0 +1,28 @@ +package com.auth0.client.mgmt.filter; + +public class EnabledClientsFilter extends BaseFilter { + /** + * Include the {@code from} parameter to specify where to start the page selection. Only applicable for endpoints that + * support checkpoint pagination. + * + * @param from the ID from which to start selection. This can be obtained from the {@code next} field returned from + * a checkpoint-paginated result. + * @return this filter instance. + */ + public EnabledClientsFilter withFrom(String from) { + parameters.put("from", from); + return this; + } + + /** + * Include the {@code take} parameter to specify the amount of results to return per page. Only applicable for endpoints that + * support checkpoint pagination. + * + * @param take the amount of entries to retrieve per page. + * @return this filter instance. + */ + public EnabledClientsFilter withTake(int take) { + parameters.put("take", take); + return this; + } +} diff --git a/src/main/java/com/auth0/client/mgmt/filter/EncryptionKeyFilter.java b/src/main/java/com/auth0/client/mgmt/filter/EncryptionKeyFilter.java new file mode 100644 index 000000000..2d9b18ff7 --- /dev/null +++ b/src/main/java/com/auth0/client/mgmt/filter/EncryptionKeyFilter.java @@ -0,0 +1,29 @@ +package com.auth0.client.mgmt.filter; + +public class EncryptionKeyFilter extends BaseFilter { + + /** + * Filter by page + * + * @param pageNumber the page number to retrieve. + * @param amountPerPage the amount of items per page to retrieve. + * @return this filter instance + */ + public EncryptionKeyFilter withPage(int pageNumber, int amountPerPage) { + parameters.put("page", pageNumber); + parameters.put("per_page", amountPerPage); + return this; + } + + /** + * Include the query summary + * + * @param includeTotals whether to include or not the query summary. + * @return this filter instance + */ + public EncryptionKeyFilter withTotals(boolean includeTotals) { + parameters.put("include_totals", includeTotals); + return this; + } + +} diff --git a/src/main/java/com/auth0/client/mgmt/filter/NetworkAclsFilter.java b/src/main/java/com/auth0/client/mgmt/filter/NetworkAclsFilter.java new file mode 100644 index 000000000..c17624ddf --- /dev/null +++ b/src/main/java/com/auth0/client/mgmt/filter/NetworkAclsFilter.java @@ -0,0 +1,28 @@ +package com.auth0.client.mgmt.filter; + +public class NetworkAclsFilter extends BaseFilter { + + /** + * Filter by page + * + * @param pageNumber the page number to retrieve. + * @param amountPerPage the amount of items per page to retrieve. + * @return this filter instance + */ + public NetworkAclsFilter withPage(int pageNumber, int amountPerPage) { + parameters.put("page", pageNumber); + parameters.put("per_page", amountPerPage); + return this; + } + + /** + * Include the query summary + * + * @param includeTotals whether to include or not the query summary. + * @return this filter instance + */ + public NetworkAclsFilter withTotals(boolean includeTotals) { + parameters.put("include_totals", includeTotals); + return this; + } +} diff --git a/src/main/java/com/auth0/client/mgmt/filter/OrganizationClientGrantsFilter.java b/src/main/java/com/auth0/client/mgmt/filter/OrganizationClientGrantsFilter.java new file mode 100644 index 000000000..5230a4145 --- /dev/null +++ b/src/main/java/com/auth0/client/mgmt/filter/OrganizationClientGrantsFilter.java @@ -0,0 +1,65 @@ +package com.auth0.client.mgmt.filter; + +/** + * Class used to filter the results received when listing the client grants associated with an organization. + * Related to the {@link com.auth0.client.mgmt.OrganizationsEntity} entity. + */ +public class OrganizationClientGrantsFilter extends BaseFilter { + + /** + * Filter by client id + * + * @param clientId only retrieve items with this client id. + * @return this filter instance + */ + public OrganizationClientGrantsFilter withClientId(String clientId) { + parameters.put("client_id", clientId); + return this; + } + + /** + * Filter by audience + * + * @param audience only retrieve the item with this audience. + * @return this filter instance + */ + public OrganizationClientGrantsFilter withAudience(String audience) { + parameters.put("audience", audience); + return this; + } + + /** + * Filter by page + * + * @param pageNumber the page number to retrieve. + * @param amountPerPage the amount of items per page to retrieve. + * @return this filter instance + */ + public OrganizationClientGrantsFilter withPage(int pageNumber, int amountPerPage) { + parameters.put("page", pageNumber); + parameters.put("per_page", amountPerPage); + return this; + } + + /** + * Include the query summary + * + * @param includeTotals whether to include or not the query summary. + * @return this filter instance + */ + public OrganizationClientGrantsFilter withTotals(boolean includeTotals) { + parameters.put("include_totals", includeTotals); + return this; + } + + /** + * Filter by grant IDs + * + * @param grantIds comma-separated list of grant IDs to filter results on. + * @return this filter instance + */ + public OrganizationClientGrantsFilter withGrantIds(String grantIds) { + parameters.put("grant_ids", grantIds); + return this; + } +} diff --git a/src/main/java/com/auth0/client/mgmt/filter/PageBasedPaginationFilter.java b/src/main/java/com/auth0/client/mgmt/filter/PageBasedPaginationFilter.java new file mode 100644 index 000000000..a11b69b83 --- /dev/null +++ b/src/main/java/com/auth0/client/mgmt/filter/PageBasedPaginationFilter.java @@ -0,0 +1,31 @@ +package com.auth0.client.mgmt.filter; + +/** + * Class that represents a filter to be used when requesting a list of items with pagination. + */ +public class PageBasedPaginationFilter extends BaseFilter{ + + /** + * Filter by page + * + * @param pageNumber the page number to retrieve. + * @param amountPerPage the amount of items per page to retrieve. + * @return this filter instance + */ + public PageBasedPaginationFilter withPage(int pageNumber, int amountPerPage) { + parameters.put("page", pageNumber); + parameters.put("per_page", amountPerPage); + return this; + } + + /** + * Include the query summary + * + * @param includeTotals whether to include or not the query summary. + * @return this filter instance + */ + public PageBasedPaginationFilter withTotals(boolean includeTotals) { + parameters.put("include_totals", includeTotals); + return this; + } +} diff --git a/src/main/java/com/auth0/client/mgmt/filter/ResourceServersFilter.java b/src/main/java/com/auth0/client/mgmt/filter/ResourceServersFilter.java index 4ff648432..ddf81dafb 100644 --- a/src/main/java/com/auth0/client/mgmt/filter/ResourceServersFilter.java +++ b/src/main/java/com/auth0/client/mgmt/filter/ResourceServersFilter.java @@ -33,4 +33,28 @@ public ResourceServersFilter withTotals(boolean includeTotals) { return this; } + /** + * Filter by specific identifier IDs (i.e. audience) + * + * @param identifiers the identifier IDs to filter by + * @return this filter instance + */ + public ResourceServersFilter withIdentifiers(String identifiers) { + parameters.put("identifiers", identifiers); + return this; + } + + /** + * Filter by checkpoint pagination support + * + * @param from the starting index identifier + * @param take the number of items to retrieve + * @return this filter instance + */ + public ResourceServersFilter withCheckpointPagination(String from, int take) { + parameters.put("from", from); + parameters.put("take", take); + return this; + } + } diff --git a/src/main/java/com/auth0/client/mgmt/filter/UserAttributeProfilesFilter.java b/src/main/java/com/auth0/client/mgmt/filter/UserAttributeProfilesFilter.java new file mode 100644 index 000000000..5822105d1 --- /dev/null +++ b/src/main/java/com/auth0/client/mgmt/filter/UserAttributeProfilesFilter.java @@ -0,0 +1,17 @@ +package com.auth0.client.mgmt.filter; + +public class UserAttributeProfilesFilter extends BaseFilter { + + /** + * Filter by checkpoint pagination support + * + * @param from the starting index identifier + * @param take the number of items to retrieve + * @return this filter instance + */ + public UserAttributeProfilesFilter withCheckpointPagination(String from, int take) { + parameters.put("from", from); + parameters.put("take", take); + return this; + } +} diff --git a/src/main/java/com/auth0/client/mgmt/filter/UserFilter.java b/src/main/java/com/auth0/client/mgmt/filter/UserFilter.java index c93edde69..51995c4eb 100644 --- a/src/main/java/com/auth0/client/mgmt/filter/UserFilter.java +++ b/src/main/java/com/auth0/client/mgmt/filter/UserFilter.java @@ -67,4 +67,16 @@ public UserFilter withFields(String fields, boolean includeFields) { super.withFields(fields, includeFields); return this; } + + /** + * Connection filter. Only applies when using search_engine=v1. + * To filter by connection with search_engine=v2|v3, use q=identities.connection:"connection_name" + * + * @param connection connection to be filtered with + * @return this filter instance + */ + public UserFilter withConnection(String connection) { + parameters.put("connection", connection); + return this; + } } diff --git a/src/main/java/com/auth0/client/mgmt/filter/UsersExportFilter.java b/src/main/java/com/auth0/client/mgmt/filter/UsersExportFilter.java index 4f6574e8b..94d9508a7 100644 --- a/src/main/java/com/auth0/client/mgmt/filter/UsersExportFilter.java +++ b/src/main/java/com/auth0/client/mgmt/filter/UsersExportFilter.java @@ -47,4 +47,15 @@ public UsersExportFilter withFields(List fields) { return this; } + /** + * ID for the connection from which you want to export users + * + * @param connectionId ID for the connection + * @see Locate the Connection ID or Name + * @return this filter instance + */ + public UsersExportFilter withConnectionId(String connectionId) { + parameters.put("connection_id", connectionId); + return this; + } } diff --git a/src/main/java/com/auth0/client/mgmt/filter/UsersImportOptions.java b/src/main/java/com/auth0/client/mgmt/filter/UsersImportOptions.java index 4aad48a49..1a9c40086 100644 --- a/src/main/java/com/auth0/client/mgmt/filter/UsersImportOptions.java +++ b/src/main/java/com/auth0/client/mgmt/filter/UsersImportOptions.java @@ -50,4 +50,15 @@ public UsersImportOptions withUpsert(boolean upsert) { return this; } + /** + * ID for the connection from which you want to export users + * + * @param connectionId ID for the connection + * @see Locate the Connection ID or Name + * @return this filter instance + */ + public UsersImportOptions withConnectionId(String connectionId) { + parameters.put("connection_id", connectionId); + return this; + } } diff --git a/src/main/java/com/auth0/exception/ClientAssertionSigningException.java b/src/main/java/com/auth0/exception/ClientAssertionSigningException.java new file mode 100644 index 000000000..1de218393 --- /dev/null +++ b/src/main/java/com/auth0/exception/ClientAssertionSigningException.java @@ -0,0 +1,26 @@ +package com.auth0.exception; + +/** + * Reqpresents an exception when creating the signed client assertion. + */ +public class ClientAssertionSigningException extends RuntimeException { + + /** + * Create a new instance. + * + * @param message the message of the exception. + */ + public ClientAssertionSigningException(String message) { + super(message); + } + + /** + * Create a new instance. + * + * @param message the message of the exception. + * @param cause the cause of the exception. + */ + public ClientAssertionSigningException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/com/auth0/exception/RateLimitException.java b/src/main/java/com/auth0/exception/RateLimitException.java index c5e79e812..9d2a15a77 100644 --- a/src/main/java/com/auth0/exception/RateLimitException.java +++ b/src/main/java/com/auth0/exception/RateLimitException.java @@ -1,5 +1,9 @@ package com.auth0.exception; +import com.auth0.net.TokenQuotaBucket; + +import java.util.Map; + /** * Represents a server error when a rate limit has been exceeded. *

@@ -14,8 +18,19 @@ public class RateLimitException extends APIException { private final long remaining; private final long reset; + private TokenQuotaBucket clientQuotaLimit; + private TokenQuotaBucket organizationQuotaLimit; + private long retryAfter; + private static final int STATUS_CODE_TOO_MANY_REQUEST = 429; + public RateLimitException(long limit, long remaining, long reset, Map values) { + super(values, STATUS_CODE_TOO_MANY_REQUEST); + this.limit = limit; + this.remaining = remaining; + this.reset = reset; + } + public RateLimitException(long limit, long remaining, long reset) { super("Rate limit reached", STATUS_CODE_TOO_MANY_REQUEST, null); this.limit = limit; @@ -47,4 +62,119 @@ public long getReset() { return reset; } + /** + * Getter for the client quota limit. + * @return The client quota limit or null if missing. + */ + public TokenQuotaBucket getClientQuotaLimit() { + return clientQuotaLimit; + } + + /** + * Getter for the organization quota limit. + * @return The organization quota limit or null if missing. + */ + public TokenQuotaBucket getOrganizationQuotaLimit() { + return organizationQuotaLimit; + } + + /** + * Getter for the retry after time in seconds. + * @return The retry after time in seconds or -1 if missing. + */ + public long getRetryAfter() { + return retryAfter; + } + + /** + * Builder class for creating instances of RateLimitException. + */ + public static class Builder { + private long limit; + private long remaining; + private long reset; + private TokenQuotaBucket clientQuotaLimit; + private TokenQuotaBucket organizationQuotaLimit; + private long retryAfter; + private Map values; + + /** + * Constructor for the Builder. + * @param limit The maximum number of requests available in the current time frame. + * @param remaining The number of remaining requests in the current time frame. + * @param reset The UNIX timestamp of the expected time when the rate limit will reset. + */ + public Builder(long limit, long remaining, long reset) { + this.limit = limit; + this.remaining = remaining; + this.reset = reset; + } + + /** + * Constructor for the Builder. + * @param limit The maximum number of requests available in the current time frame. + * @param remaining The number of remaining requests in the current time frame. + * @param reset The UNIX timestamp of the expected time when the rate limit will reset. + * @param values The values map. + */ + public Builder(long limit, long remaining, long reset, Map values) { + this.limit = limit; + this.remaining = remaining; + this.reset = reset; + this.values = values; + } + + /** + * Sets the client quota limit. + * @param clientQuotaLimit The client quota limit. + * @return The Builder instance. + */ + public Builder clientQuotaLimit(TokenQuotaBucket clientQuotaLimit) { + this.clientQuotaLimit = clientQuotaLimit; + return this; + } + + /** + * Sets the organization quota limit. + * @param organizationQuotaLimit The organization quota limit. + * @return The Builder instance. + */ + public Builder organizationQuotaLimit(TokenQuotaBucket organizationQuotaLimit) { + this.organizationQuotaLimit = organizationQuotaLimit; + return this; + } + + /** + * Sets the retry after time in seconds. + * @param retryAfter The retry after time in seconds. + * @return The Builder instance. + */ + public Builder retryAfter(long retryAfter) { + this.retryAfter = retryAfter; + return this; + } + + /** + * Sets the values map. + * @param values The values map. + * @return The Builder instance. + */ + public Builder values(Map values) { + this.values = values; + return this; + } + + public RateLimitException build() { + RateLimitException exception = (this.values != null) + ? new RateLimitException(this.limit, this.remaining, this.reset, this.values) + : new RateLimitException(this.limit, this.remaining, this.reset); + + exception.clientQuotaLimit = this.clientQuotaLimit; + exception.organizationQuotaLimit = this.organizationQuotaLimit; + exception.retryAfter = this.retryAfter; + + return exception; + } + } + } diff --git a/src/main/java/com/auth0/json/ObjectMapperProvider.java b/src/main/java/com/auth0/json/ObjectMapperProvider.java new file mode 100644 index 000000000..134a36697 --- /dev/null +++ b/src/main/java/com/auth0/json/ObjectMapperProvider.java @@ -0,0 +1,22 @@ +package com.auth0.json; + +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * Provides access to a single {@link ObjectMapper} instance for the serialization and deserialization of JSON data. + * This class is for internal use only and is subject to change without notice. + */ +public class ObjectMapperProvider { + + private static final ObjectMapper objectMapper = new ObjectMapper(); + + // prevent instantiation + private ObjectMapperProvider() {} + + /** + * @return the {@code ObjectMapper} instance to process JSON data + */ + public static ObjectMapper getMapper() { + return objectMapper; + } +} diff --git a/src/main/java/com/auth0/json/auth/BackChannelAuthorizeResponse.java b/src/main/java/com/auth0/json/auth/BackChannelAuthorizeResponse.java new file mode 100644 index 000000000..1765867d5 --- /dev/null +++ b/src/main/java/com/auth0/json/auth/BackChannelAuthorizeResponse.java @@ -0,0 +1,45 @@ +package com.auth0.json.auth; + +import com.fasterxml.jackson.annotation.*; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class BackChannelAuthorizeResponse { + @JsonProperty("auth_req_id") + private String authReqId; + @JsonProperty("expires_in") + private Long expiresIn; + @JsonProperty("interval") + private Integer interval; + + @JsonCreator + public BackChannelAuthorizeResponse(@JsonProperty("auth_req_id") String authReqId, @JsonProperty("expires_in") Long expiresIn, @JsonProperty("interval") Integer interval) { + this.authReqId = authReqId; + this.expiresIn = expiresIn; + this.interval = interval; + } + + /** + * Getter for the Auth Request ID. + * @return the Auth Request ID. + */ + public String getAuthReqId() { + return authReqId; + } + + /** + * Getter for the Expires In value. + * @return the Expires In value. + */ + public Long getExpiresIn() { + return expiresIn; + } + + /** + * Getter for the Interval value. + * @return the Interval value. + */ + public Integer getInterval() { + return interval; + } +} diff --git a/src/main/java/com/auth0/json/auth/BackChannelTokenResponse.java b/src/main/java/com/auth0/json/auth/BackChannelTokenResponse.java new file mode 100644 index 000000000..ab632f98c --- /dev/null +++ b/src/main/java/com/auth0/json/auth/BackChannelTokenResponse.java @@ -0,0 +1,34 @@ +package com.auth0.json.auth; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class BackChannelTokenResponse { + @JsonProperty("access_token") + private String accessToken; + @JsonProperty("id_token") + private String idToken; + @JsonProperty("expires_in") + private long expiresIn; + @JsonProperty("scope") + private String scope; + + public String getAccessToken() { + return accessToken; + } + + public String getIdToken() { + return idToken; + } + + public long getExpiresIn() { + return expiresIn; + } + + public String getScope() { + return scope; + } +} diff --git a/src/main/java/com/auth0/json/auth/CreatedOobResponse.java b/src/main/java/com/auth0/json/auth/CreatedOobResponse.java new file mode 100644 index 000000000..b58d24e1b --- /dev/null +++ b/src/main/java/com/auth0/json/auth/CreatedOobResponse.java @@ -0,0 +1,47 @@ +package com.auth0.json.auth; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class CreatedOobResponse { + + @JsonProperty("oob_code") + private String oobCode; + + @JsonProperty("barcode_uri") + private String barcodeUri; + + @JsonProperty("authenticator_type") + private String authenticatorType; + + @JsonProperty("oob_channel") + private String oobChannel; + + @JsonProperty("recovery_codes") + private List recoveryCodes; + + public String getOobCode() { + return oobCode; + } + + public String getBarcodeUri() { + return barcodeUri; + } + + public String getAuthenticatorType() { + return authenticatorType; + } + + public List getRecoveryCodes() { + return recoveryCodes; + } + + public String getOobChannel() { + return oobChannel; + } +} diff --git a/src/main/java/com/auth0/json/auth/CreatedOtpResponse.java b/src/main/java/com/auth0/json/auth/CreatedOtpResponse.java new file mode 100644 index 000000000..72f739be3 --- /dev/null +++ b/src/main/java/com/auth0/json/auth/CreatedOtpResponse.java @@ -0,0 +1,41 @@ +package com.auth0.json.auth; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class CreatedOtpResponse { + + @JsonProperty("secret") + private String secret; + + @JsonProperty("barcode_uri") + private String barcodeUri; + + @JsonProperty("authenticator_type") + private String authenticatorType; + + @JsonProperty("recovery_codes") + private List recoveryCodes; + + public String getSecret() { + return secret; + } + + public String getBarcodeUri() { + return barcodeUri; + } + + public String getAuthenticatorType() { + return authenticatorType; + } + + public List getRecoveryCodes() { + return recoveryCodes; + } + +} diff --git a/src/main/java/com/auth0/json/auth/CreatedUser.java b/src/main/java/com/auth0/json/auth/CreatedUser.java index 79d05378b..c2d0b6ef7 100644 --- a/src/main/java/com/auth0/json/auth/CreatedUser.java +++ b/src/main/java/com/auth0/json/auth/CreatedUser.java @@ -22,6 +22,8 @@ public class CreatedUser { private String username; @JsonProperty("email_verified") private Boolean emailVerified; + @JsonProperty("phone_number") + private String phoneNumber; @JsonProperty("_id") @JsonAlias({"_id", "id", "user_id"}) @@ -44,4 +46,8 @@ public Boolean isEmailVerified() { return emailVerified; } + @JsonProperty("phone_number") + public String getPhoneNumber() { + return phoneNumber; + } } diff --git a/src/main/java/com/auth0/json/auth/MfaAuthenticator.java b/src/main/java/com/auth0/json/auth/MfaAuthenticator.java new file mode 100644 index 000000000..67d7f80a5 --- /dev/null +++ b/src/main/java/com/auth0/json/auth/MfaAuthenticator.java @@ -0,0 +1,45 @@ +package com.auth0.json.auth; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class MfaAuthenticator { + + @JsonProperty("id") + private String id; + + @JsonProperty("authenticator_type") + private String authenticatorType; + + @JsonProperty("active") + private boolean active; + + @JsonProperty("name") + private String name; + + @JsonProperty("oob_channel") + private String oobChannel; + + public String getId() { + return id; + } + + public String getAuthenticatorType() { + return authenticatorType; + } + + public boolean isActive() { + return active; + } + + public String getName() { + return name; + } + + public String getOobChannel() { + return oobChannel; + } +} diff --git a/src/main/java/com/auth0/json/auth/MfaChallengeResponse.java b/src/main/java/com/auth0/json/auth/MfaChallengeResponse.java new file mode 100644 index 000000000..67a0382a4 --- /dev/null +++ b/src/main/java/com/auth0/json/auth/MfaChallengeResponse.java @@ -0,0 +1,31 @@ +package com.auth0.json.auth; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class MfaChallengeResponse { + + @JsonProperty("challenge_type") + private String challengeType; + + @JsonProperty("binding_method") + private String bindingMethod; + + @JsonProperty("oob_code") + private String oobCode; + + public String getChallengeType() { + return challengeType; + } + + public String getBindingMethod() { + return bindingMethod; + } + + public String getOobCode() { + return oobCode; + } +} diff --git a/src/main/java/com/auth0/json/auth/PushedAuthorizationResponse.java b/src/main/java/com/auth0/json/auth/PushedAuthorizationResponse.java new file mode 100644 index 000000000..347d0c4e6 --- /dev/null +++ b/src/main/java/com/auth0/json/auth/PushedAuthorizationResponse.java @@ -0,0 +1,33 @@ +package com.auth0.json.auth; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Represents the response from a Pushed Authorization Request (PAR). + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class PushedAuthorizationResponse { + + @JsonProperty("request_uri") + private String requestURI; + @JsonProperty("expires_in") + private Integer expiresIn; + + @JsonCreator + public PushedAuthorizationResponse(@JsonProperty("request_uri") String requestURI, @JsonProperty("expires_in") Integer expiresIn) { + this.requestURI = requestURI; + this.expiresIn = expiresIn; + } + + public String getRequestURI() { + return requestURI; + } + + public Integer getExpiresIn() { + return expiresIn; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/PageDeserializer.java b/src/main/java/com/auth0/json/mgmt/PageDeserializer.java index 63a70ca27..63994f71a 100644 --- a/src/main/java/com/auth0/json/mgmt/PageDeserializer.java +++ b/src/main/java/com/auth0/json/mgmt/PageDeserializer.java @@ -1,9 +1,9 @@ package com.auth0.json.mgmt; +import com.auth0.json.ObjectMapperProvider; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.type.CollectionType; @@ -23,7 +23,6 @@ public abstract class PageDeserializer extends StdDeserializer { private final String itemsPropertyName; private final Class uClazz; - private static final ObjectMapper mapper = new ObjectMapper(); protected PageDeserializer(Class clazz, String arrayName) { super(Object.class); @@ -82,7 +81,7 @@ private String getStringValue(JsonNode node) { } private List getArrayElements(ArrayNode array) throws IOException { - CollectionType type = mapper.getTypeFactory().constructCollectionType(List.class, uClazz); - return mapper.readerFor(type).readValue(array); + CollectionType type = ObjectMapperProvider.getMapper().getTypeFactory().constructCollectionType(List.class, uClazz); + return ObjectMapperProvider.getMapper().readerFor(type).readValue(array); } } diff --git a/src/main/java/com/auth0/json/mgmt/attackprotection/BreachedPassword.java b/src/main/java/com/auth0/json/mgmt/attackprotection/BreachedPassword.java index ac5dfcb3e..53b1caed9 100644 --- a/src/main/java/com/auth0/json/mgmt/attackprotection/BreachedPassword.java +++ b/src/main/java/com/auth0/json/mgmt/attackprotection/BreachedPassword.java @@ -23,6 +23,8 @@ public class BreachedPassword { private List shields; @JsonProperty("admin_notification_frequency") private List adminNotificationFrequency; + @JsonProperty("stage") + private BreachedPasswordStage stage; /** * @return whether or not breached password detection is active. @@ -84,5 +86,19 @@ public void setAdminNotificationFrequency(List adminNotificationFrequenc this.adminNotificationFrequency = adminNotificationFrequency; } + /** + * @return the per-stage configuration options + */ + public BreachedPasswordStage getStage() { + return stage; + } + + /** + * Sets the per-stage configuration options. + * @param stage the per-stage configuration options. + */ + public void setStage(BreachedPasswordStage stage) { + this.stage = stage; + } } diff --git a/src/main/java/com/auth0/json/mgmt/attackprotection/BreachedPasswordStage.java b/src/main/java/com/auth0/json/mgmt/attackprotection/BreachedPasswordStage.java new file mode 100644 index 000000000..d9b946155 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/attackprotection/BreachedPasswordStage.java @@ -0,0 +1,34 @@ +package com.auth0.json.mgmt.attackprotection; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Represents the BreachedPassword stage configuration options + * + * @see com.auth0.client.mgmt.AttackProtectionEntity + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class BreachedPasswordStage { + + @JsonProperty("pre-user-registration") + BreachedPasswordStageEntry preUserRegistrationStage; + + /** + * Get the pre-user-registration stage entry. + * @return the pre-user-registration stage entry. + */ + public BreachedPasswordStageEntry getPreUserRegistrationStage() { + return preUserRegistrationStage; + } + + /** + * Set the pre-user-registration stage entry. + * @param preUserRegistrationStage the pre-user-registration stage entry. + */ + public void setPreUserRegistrationStage(BreachedPasswordStageEntry preUserRegistrationStage) { + this.preUserRegistrationStage = preUserRegistrationStage; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/attackprotection/BreachedPasswordStageEntry.java b/src/main/java/com/auth0/json/mgmt/attackprotection/BreachedPasswordStageEntry.java new file mode 100644 index 000000000..0db6af1b6 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/attackprotection/BreachedPasswordStageEntry.java @@ -0,0 +1,36 @@ +package com.auth0.json.mgmt.attackprotection; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * Represents the per-stage configuration options for BreachedPasswordStage + * + * @see Stage + * @see com.auth0.client.mgmt.AttackProtectionEntity + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class BreachedPasswordStageEntry { + @JsonProperty("shields") + private List shields; + + /** + * Get the shields for this Stage entry + * @return the shields for this Stage entry + */ + public List getShields() { + return shields; + } + + /** + * Sets the shields for this Stage entry + * @param shields the shields for this Stage entry + */ + public void setShields(List shields) { + this.shields = shields; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/Token.java b/src/main/java/com/auth0/json/mgmt/blacklists/Token.java similarity index 97% rename from src/main/java/com/auth0/json/mgmt/Token.java rename to src/main/java/com/auth0/json/mgmt/blacklists/Token.java index 4a520bf33..f8f8543ce 100644 --- a/src/main/java/com/auth0/json/mgmt/Token.java +++ b/src/main/java/com/auth0/json/mgmt/blacklists/Token.java @@ -1,4 +1,4 @@ -package com.auth0.json.mgmt; +package com.auth0.json.mgmt.blacklists; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; diff --git a/src/main/java/com/auth0/json/mgmt/client/Client.java b/src/main/java/com/auth0/json/mgmt/client/Client.java index c153a4359..62147bfde 100644 --- a/src/main/java/com/auth0/json/mgmt/client/Client.java +++ b/src/main/java/com/auth0/json/mgmt/client/Client.java @@ -1,5 +1,6 @@ package com.auth0.json.mgmt.client; +import com.auth0.json.mgmt.tokenquota.TokenQuota; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; @@ -30,6 +31,8 @@ public class Client { private String logoUri; @JsonProperty("is_first_party") private Boolean isFirstParty; + @JsonProperty("is_token_endpoint_ip_header_trusted") + private Boolean isTokenEndpointIpHeaderTrusted; @JsonProperty("oidc_conformant") private Boolean oidcConformant; @JsonProperty("callbacks") @@ -86,10 +89,26 @@ public class Client { private String tenant; @JsonProperty("global") private Boolean global; - @JsonProperty("cross_origin_auth") + @JsonProperty("cross_origin_authentication") private Boolean crossOriginAuth; @JsonProperty("cross_origin_loc") private String crossOriginLoc; + @JsonProperty("client_authentication_methods") + private ClientAuthenticationMethods clientAuthenticationMethods; + @JsonProperty("require_pushed_authorization_requests") + private Boolean requiresPushedAuthorizationRequests; + @JsonProperty("oidc_backchannel_logout") + private OIDCBackchannelLogout oidcBackchannelLogout; + @JsonProperty("signed_request_object") + private SignedRequest signedRequest; + @JsonProperty("compliance_level") + private String complianceLevel; + @JsonProperty("require_proof_of_possession") + private Boolean requireProofOfPossession; + @JsonProperty("default_organization") + private ClientDefaultOrganization defaultOrganization; + @JsonProperty("token_quota") + private TokenQuota tokenQuota; /** * Getter for the name of the tenant this client belongs to. @@ -137,6 +156,17 @@ public Client(@JsonProperty("name") String name) { this.name = name; } + /** + * Creates a new Application instance setting the name and client id properties. + * + * @param name of the application. + * @param clientId the client id of the application. + */ + public Client(String name, String clientId) { + this.name = name; + this.clientId = clientId; + } + /** * Getter for the name of the application. * @@ -267,6 +297,26 @@ public void setIsFirstParty(Boolean isFirstParty) { this.isFirstParty = isFirstParty; } + /** + * Whether the token endpoint IP header is trusted for this application. + * + * @return true if the token endpoint IP header is trusted, false otherwise. + */ + @JsonProperty("is_token_endpoint_ip_header_trusted") + public Boolean getIsTokenEndpointIpHeaderTrusted() { + return isTokenEndpointIpHeaderTrusted; + } + + /** + * Setter for whether the token endpoint IP header is trusted for this application. + * + * @param isTokenEndpointIpHeaderTrusted whether the token endpoint IP header is trusted or not. + */ + @JsonProperty("is_token_endpoint_ip_header_trusted") + public void setIsTokenEndpointIpHeaderTrusted(Boolean isTokenEndpointIpHeaderTrusted) { + this.isTokenEndpointIpHeaderTrusted = isTokenEndpointIpHeaderTrusted; + } + /** * Whether this application will conform to strict Open ID Connect specifications or not. * @@ -762,7 +812,7 @@ public void setOrganizationRequireBehavior(String organizationRequireBehavior) { * Setter whether this client can be used to make cross-origin authentication requests (true) or it is not allowed to make such requests (false). * @param crossOriginAuth whether an application can make cross-origin authentication requests or not */ - @JsonProperty("cross_origin_auth") + @JsonProperty("cross_origin_authentication") public void setCrossOriginAuth(Boolean crossOriginAuth) { this.crossOriginAuth = crossOriginAuth; } @@ -771,7 +821,7 @@ public void setCrossOriginAuth(Boolean crossOriginAuth) { * Whether this client can be used to make cross-origin authentication requests (true) or it is not allowed to make such requests (false). * @return true if application can make cross-origin authentication requests, false otherwise */ - @JsonProperty("cross_origin_auth") + @JsonProperty("cross_origin_authentication") public Boolean getCrossOriginAuth() { return crossOriginAuth; } @@ -793,5 +843,121 @@ public void setCrossOriginLoc(String crossOriginLoc) { public String getCrossOriginLoc() { return crossOriginLoc; } + + public void setClientAuthenticationMethods(ClientAuthenticationMethods clientAuthenticationMethods) { + this.clientAuthenticationMethods = clientAuthenticationMethods; + } + + public ClientAuthenticationMethods getClientAuthenticationMethods() { + return clientAuthenticationMethods; + } + + /** + * @return whether this client requires pushed authorization requests or not. + */ + public Boolean getRequiresPushedAuthorizationRequests() { + return requiresPushedAuthorizationRequests; + } + + /** + * Sets whether the client requires pushed authorization requests or not. + * @param requiresPushedAuthorizationRequests true if the client should require pushed authorization requests, false if not. + */ + public void setRequiresPushedAuthorizationRequests(Boolean requiresPushedAuthorizationRequests) { + this.requiresPushedAuthorizationRequests = requiresPushedAuthorizationRequests; + } + + /** + * @return the value of the {@code oidc_backchannel_logout} property. + */ + public OIDCBackchannelLogout getOidcBackchannelLogout() { + return oidcBackchannelLogout; + } + + /** + * Sets the {@code oidc_backchannel_logout} property. + * @param oidcBackchannelLogout the value to set the {@code oidc_backchannel_logout} property to. + */ + public void setOidcBackchannelLogout(OIDCBackchannelLogout oidcBackchannelLogout) { + this.oidcBackchannelLogout = oidcBackchannelLogout; + } + + /** + * @return the value of the {@code signed_request_object} field. + */ + public SignedRequest getSignedRequest() { + return signedRequest; + } + + /** + * Sets the value of the {@code SignedRequest} field. + * + * @param signedRequest the value to set the {@code signed_request_field} field to. + */ + public void setSignedRequest(SignedRequest signedRequest) { + this.signedRequest = signedRequest; + } + + /** + * @return the value of the {@code compliance_level} field + */ + public String getComplianceLevel() { + return complianceLevel; + } + + /** + * Sets the value of the {@code compliance_level} field + * @param complianceLevel the value of the {@code compliance_level} field + */ + public void setComplianceLevel(String complianceLevel) { + this.complianceLevel = complianceLevel; + } + + /** + * @return the value of the {@code require_proof_of_possession} field + */ + public Boolean getRequireProofOfPossession() { + return requireProofOfPossession; + } + + /** + * Sets the value of the {@code require_proof_of_possession} field + * @param requireProofOfPossession the value of the {@code require_proof_of_possession} field + */ + public void setRequireProofOfPossession(Boolean requireProofOfPossession) { + this.requireProofOfPossession = requireProofOfPossession; + } + + /** + * Getter for the default organization configuration. + * @return the default organization configuration. + */ + public ClientDefaultOrganization getDefaultOrganization() { + return defaultOrganization; + } + + /** + * Setter for the default organization configuration. + * @param defaultOrganization the default organization configuration to set. + */ + public void setDefaultOrganization(ClientDefaultOrganization defaultOrganization) { + this.defaultOrganization = defaultOrganization; + } + + /** + * Getter for the token quota configuration. + * @return the token quota configuration. + */ + public TokenQuota getTokenQuota() { + return tokenQuota; + } + + /** + * Setter for the token quota configuration. + * @param tokenQuota the token quota configuration to set. + */ + public void setTokenQuota(TokenQuota tokenQuota) { + this.tokenQuota = tokenQuota; + } } diff --git a/src/main/java/com/auth0/json/mgmt/client/ClientAuthenticationMethods.java b/src/main/java/com/auth0/json/mgmt/client/ClientAuthenticationMethods.java new file mode 100644 index 000000000..bc7b22aa6 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/client/ClientAuthenticationMethods.java @@ -0,0 +1,71 @@ +package com.auth0.json.mgmt.client; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Class that represents an Auth0 Application authentication methods. Related to the {@link com.auth0.client.mgmt.ClientsEntity} entity. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ClientAuthenticationMethods { + + @JsonProperty("private_key_jwt") + private PrivateKeyJwt privateKeyJwt; + @JsonProperty("self_signed_tls_client_auth") + private SelfSignedTLSClientAuth selfSignedTLSClientAuth; + @JsonProperty("tls_client_auth") + private TLSClientAuth tlsClientAuth; + + public ClientAuthenticationMethods() { + + } + + /** + * Create a new instance. + * @param privateKeyJwt the value of the {@code private_key_jwt} field. + */ + public ClientAuthenticationMethods(PrivateKeyJwt privateKeyJwt) { + this(privateKeyJwt, null, null); + } + + /** + * Create a new instance. + * @param privateKeyJwt the value of the {@code private_key_jwt} field. + * @param selfSignedTLSClientAuth the value of the {@code self_signed_tls_client_auth} field. + */ + public ClientAuthenticationMethods(PrivateKeyJwt privateKeyJwt, SelfSignedTLSClientAuth selfSignedTLSClientAuth) { + this(privateKeyJwt, selfSignedTLSClientAuth, null); + } + + /** + * Create a new instance. + * @param privateKeyJwt the value of the {@code private_key_jwt} field. + * @param selfSignedTLSClientAuth the value of the {@code self_signed_tls_client_auth} field. + * @param tlsClientAuth the value of the {@code tls_client_auth} field. + */ + public ClientAuthenticationMethods(PrivateKeyJwt privateKeyJwt, SelfSignedTLSClientAuth selfSignedTLSClientAuth, TLSClientAuth tlsClientAuth) { + this.privateKeyJwt = privateKeyJwt; + this.selfSignedTLSClientAuth = selfSignedTLSClientAuth; + this.tlsClientAuth = tlsClientAuth; + } + + public PrivateKeyJwt getPrivateKeyJwt() { + return privateKeyJwt; + } + + /** + * @return the value of the {@code self_signed_tls_client_auth} field + */ + public SelfSignedTLSClientAuth getSelfSignedTLSClientAuth() { + return selfSignedTLSClientAuth; + } + + /** + * @return the value of the {@code tls_client_auth} field + */ + public TLSClientAuth getTlsClientAuth() { + return tlsClientAuth; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/client/ClientDefaultOrganization.java b/src/main/java/com/auth0/json/mgmt/client/ClientDefaultOrganization.java new file mode 100644 index 000000000..3512f6b80 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/client/ClientDefaultOrganization.java @@ -0,0 +1,57 @@ +package com.auth0.json.mgmt.client; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ClientDefaultOrganization { + @JsonProperty("flows") + private List flows; + @JsonProperty("organization_id") + private String organizationId; + + public ClientDefaultOrganization() { + + } + + public ClientDefaultOrganization(List flows, String organizationId) { + this.flows = flows; + this.organizationId = organizationId; + } + + /** + * Getter for the supported flows. + * @return the supported flows. + */ + public List getFlows() { + return flows; + } + + /** + * Setter for the supported flows. + * @param flows the supported flows to set. + */ + public void setFlows(List flows) { + this.flows = flows; + } + + /** + * Getter for the organization_id. + * @return the organization_id. + */ + public String getOrganizationId() { + return organizationId; + } + + /** + * Setter for the organization_id. + * @param organizationId the organization_id to set. + */ + public void setOrganizationId(String organizationId) { + this.organizationId = organizationId; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/client/Credential.java b/src/main/java/com/auth0/json/mgmt/client/Credential.java new file mode 100644 index 000000000..d6a7ff181 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/client/Credential.java @@ -0,0 +1,208 @@ +package com.auth0.json.mgmt.client; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Date; + +/** + * Class that represents an Auth0 application credential object. Related to the {@link com.auth0.client.mgmt.ClientsEntity} entity. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class Credential { + + @JsonProperty("credential_type") + private String credentialType; + @JsonProperty("name") + private String name; + @JsonProperty("pem") + private String pem; + + @JsonProperty("id") + private String id; + @JsonProperty("kid") + private String kid; + @JsonProperty("thumbprint") + private String thumbprint; + @JsonProperty("alg") + private String alg; + @JsonProperty("parse_expiry_from_cert") + private Boolean parseExpiryFromCert; + @JsonProperty("subject_dn") + private String subjectDn; + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JsonProperty("created_at") + private Date createdAt; + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JsonProperty("updated_at") + private Date updatedAt; + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JsonProperty("expires_at") + private Date expiresAt; + + /** + * Create a new credential + * @param credentialType the credential type + * @param pem the PEM + */ + public Credential(String credentialType, String pem) { + this.credentialType = credentialType; + this.pem = pem; + } + + /** + * Create a new credential + * @param id the ID of the credential + */ + public Credential(String id) { + this.id = id; + } + + /** + * Create a new credential + */ + public Credential() {} + + /** + * @return the credential type + */ + public String getCredentialType() { + return credentialType; + } + + /** + * Sets the credential type + * @param credentialType the credential type + */ + public void setCredentialType(String credentialType) { + this.credentialType = credentialType; + } + + /** + * @return the credential name + */ + public String getName() { + return name; + } + + /** + * Sets the credential name + * @param name the name of the credential + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return the credential's PEM + */ + public String getPem() { + return pem; + } + + /** + * Sets the credential's PEM + * @param pem the PEM of the credential + */ + public void setPem(String pem) { + this.pem = pem; + } + + /** + * @return the ID of the credential + */ + public String getId() { + return id; + } + + /** + * @return the KID of the credential + */ + public String getKid() { + return kid; + } + + /** + * @return the thumbprint of the credential + */ + public String getThumbprint() { + return thumbprint; + } + + /** + * @return the date the credential was created at + */ + public Date getCreatedAt() { + return createdAt; + } + + /** + * @return the algorithm of this credential + */ + public String getAlg() { + return alg; + } + + /** + * Set the algorithm + * @param alg the algorithm + */ + public void setAlg(String alg) { + this.alg = alg; + } + + /** + * @return the time this credential was last updated + */ + public Date getUpdatedAt() { + return updatedAt; + } + + /** + * @return the expiration time of this credential + */ + public Date getExpiresAt() { + return expiresAt; + } + + /** + * Set the expires_at value for this credential + * @param expiresAt the time this credential should expire + */ + public void setExpiresAt(Date expiresAt) { + this.expiresAt = expiresAt; + } + + /** + * @return whether the expiry will be parsed from the x509 certificate + */ + public Boolean getParseExpiryFromCert() { + return parseExpiryFromCert; + } + + /** + * Whether to parse expiry from x509 certificate + * @param parseExpiryFromCert true to parse expiry; false otherwise. + */ + public void setParseExpiryFromCert(Boolean parseExpiryFromCert) { + this.parseExpiryFromCert = parseExpiryFromCert; + } + + /** + * @return the value of the {@code subject_dn} field + */ + public String getSubjectDn() { + return subjectDn; + } + + /** + * Sets the value of the {@code subject_dn} field + * @param subjectDn the value of the {@code subject_dn} field + */ + public void setSubjectDn(String subjectDn) { + this.subjectDn = subjectDn; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/client/OIDCBackchannelLogout.java b/src/main/java/com/auth0/json/mgmt/client/OIDCBackchannelLogout.java new file mode 100644 index 000000000..4f95b70cc --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/client/OIDCBackchannelLogout.java @@ -0,0 +1,36 @@ +package com.auth0.json.mgmt.client; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * Represents the value of the {@code oidc_backchannel_logout} property on an Auth0 application.\ + * @see Client + * @see com.auth0.client.mgmt.ClientsEntity + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class OIDCBackchannelLogout { + + @JsonProperty("backchannel_logout_urls") + private List backchannelLogoutUrls; + + /** + * Create a new instance with the given list of Logout URIs that will receive a {@code logout_token} when selected Back-Channel Logout Initiators occur. + * @param backchannelLogoutUrls the list of allowed backchannel logout URLs. + */ + public OIDCBackchannelLogout(@JsonProperty("backchannel_logout_urls") List backchannelLogoutUrls) { + this.backchannelLogoutUrls = backchannelLogoutUrls; + } + + /** + * @return the list of Logout URIs that will receive a {@code logout_token} when selected Back-Channel Logout Initiators occur. + */ + public List getBackchannelLogoutUrls() { + return this.backchannelLogoutUrls; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/client/PrivateKeyJwt.java b/src/main/java/com/auth0/json/mgmt/client/PrivateKeyJwt.java new file mode 100644 index 000000000..1cb674ce3 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/client/PrivateKeyJwt.java @@ -0,0 +1,38 @@ +package com.auth0.json.mgmt.client; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * Class that represents an Auth0 Application private key JWT authentication method. Related to the {@link com.auth0.client.mgmt.ClientsEntity} entity. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class PrivateKeyJwt { + + @JsonProperty("credentials") + private List credentials; + + /** + * Create a new instance + */ + public PrivateKeyJwt() {} + + /** + * Create a new instance + * @param credentials the credentials to use + */ + public PrivateKeyJwt(List credentials) { + this.credentials = credentials; + } + + /** + * @return the credentials + */ + public List getCredentials() { + return credentials; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/client/SelfSignedTLSClientAuth.java b/src/main/java/com/auth0/json/mgmt/client/SelfSignedTLSClientAuth.java new file mode 100644 index 000000000..e73d2be02 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/client/SelfSignedTLSClientAuth.java @@ -0,0 +1,34 @@ +package com.auth0.json.mgmt.client; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * Class that represents an Auth0 Application self-signed TLS client authentication method. Related to the {@link com.auth0.client.mgmt.ClientsEntity} entity. + */ + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class SelfSignedTLSClientAuth { + + @JsonProperty("credentials") + private List credentials; + + /** + * Create a new instance + * @param credentials the credentials to use + */ + public SelfSignedTLSClientAuth(@JsonProperty("credentials") List credentials) { + this.credentials = credentials; + } + + /** + * @return the credentials + */ + public List getCredentials() { + return credentials; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/client/SignedRequest.java b/src/main/java/com/auth0/json/mgmt/client/SignedRequest.java new file mode 100644 index 000000000..2854f690d --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/client/SignedRequest.java @@ -0,0 +1,44 @@ +package com.auth0.json.mgmt.client; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * Class that represents an Auth0 Application signed request object. Related to the {@link com.auth0.client.mgmt.ClientsEntity} entity. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class SignedRequest { + + @JsonProperty("required") + private Boolean required; + @JsonProperty("credentials") + private List credentials; + + /** + * @return the value of the {@code credentials} field + */ + public List getCredentials() { + return credentials; + } + + /** + * Sets the value of the {@code credentials} field + * + * @param credentials the value of the {@code credentials} field + */ + public void setCredentials(List credentials) { + this.credentials = credentials; + } + + public Boolean getRequired() { + return required; + } + + public void setRequired(Boolean required) { + this.required = required; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/client/TLSClientAuth.java b/src/main/java/com/auth0/json/mgmt/client/TLSClientAuth.java new file mode 100644 index 000000000..05e896af1 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/client/TLSClientAuth.java @@ -0,0 +1,32 @@ +package com.auth0.json.mgmt.client; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * Class that represents an Auth0 Application TLS client authentication method. Related to the {@link com.auth0.client.mgmt.ClientsEntity} entity. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class TLSClientAuth { + @JsonProperty("credentials") + private List credentials; + + /** + * Create a new instance + * @param credentials the credentials to use + */ + public TLSClientAuth(@JsonProperty("credentials") List credentials) { + this.credentials = credentials; + } + + /** + * @return the credentials + */ + public List getCredentials() { + return credentials; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/clientgrants/ClientGrant.java b/src/main/java/com/auth0/json/mgmt/clientgrants/ClientGrant.java new file mode 100644 index 000000000..86a6a3a4b --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/clientgrants/ClientGrant.java @@ -0,0 +1,127 @@ +package com.auth0.json.mgmt.clientgrants; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * Class that represents an Auth0 Client Grant object. Related to the {@link com.auth0.client.mgmt.ClientGrantsEntity} entity. + */ +@SuppressWarnings("unused") +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ClientGrant { + + @JsonProperty("id") + private String id; + @JsonProperty("client_id") + private String clientId; + @JsonProperty("audience") + private String audience; + @JsonProperty("scope") + private List scope; + @JsonProperty("organization_usage") + private String organizationUsage; + @JsonProperty("allow_any_organization") + private Boolean allowAnyOrganization; + + /** + * Getter for the id of the client grant. + * + * @return the id. + */ + @JsonProperty("id") + public String getId() { + return id; + } + + /** + * Getter for the client id of the application. + * + * @return the application's client id. + */ + @JsonProperty("client_id") + public String getClientId() { + return clientId; + } + + /** + * Setter for the application's client id. + * + * @param clientId the application's client id to set. + */ + @JsonProperty("client_id") + public void setClientId(String clientId) { + this.clientId = clientId; + } + + /** + * Getter for the audience. + * + * @return the audience. + */ + @JsonProperty("audience") + public String getAudience() { + return audience; + } + + /** + * Setter for the audience. + * + * @param audience the audience to set. + */ + @JsonProperty("audience") + public void setAudience(String audience) { + this.audience = audience; + } + + /** + * Getter for the scope. + * + * @return the scope. + */ + @JsonProperty("scope") + public List getScope() { + return scope; + } + + /** + * Setter for the scope. + * + * @param scope the scope to set. + */ + @JsonProperty("scope") + public void setScope(List scope) { + this.scope = scope; + } + + /** + * @return the organization use + */ + public String getOrganizationUsage() { + return organizationUsage; + } + + /** + * @param organizationUsage the value of {@code organization_usage} to set. + */ + public void setOrganizationUsage(String organizationUsage) { + this.organizationUsage = organizationUsage; + } + + /** + * @return the value of {@code allow_any_organization} + */ + public Boolean getAllowAnyOrganization() { + return allowAnyOrganization; + } + + /** + * @param allowAnyOrganization the value of {@code allow_any_organization} to set. + */ + public void setAllowAnyOrganization(Boolean allowAnyOrganization) { + this.allowAnyOrganization = allowAnyOrganization; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/ClientGrantsPage.java b/src/main/java/com/auth0/json/mgmt/clientgrants/ClientGrantsPage.java similarity index 91% rename from src/main/java/com/auth0/json/mgmt/ClientGrantsPage.java rename to src/main/java/com/auth0/json/mgmt/clientgrants/ClientGrantsPage.java index a78a39103..2f38a8bf8 100644 --- a/src/main/java/com/auth0/json/mgmt/ClientGrantsPage.java +++ b/src/main/java/com/auth0/json/mgmt/clientgrants/ClientGrantsPage.java @@ -1,5 +1,6 @@ -package com.auth0.json.mgmt; +package com.auth0.json.mgmt.clientgrants; +import com.auth0.json.mgmt.Page; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; @@ -23,4 +24,4 @@ public ClientGrantsPage(Integer start, Integer length, Integer total, Integer li super(start, length, total, limit, items); } -} \ No newline at end of file +} diff --git a/src/main/java/com/auth0/json/mgmt/ClientGrantsPageDeserializer.java b/src/main/java/com/auth0/json/mgmt/clientgrants/ClientGrantsPageDeserializer.java similarity index 90% rename from src/main/java/com/auth0/json/mgmt/ClientGrantsPageDeserializer.java rename to src/main/java/com/auth0/json/mgmt/clientgrants/ClientGrantsPageDeserializer.java index 560c4715b..179412db9 100644 --- a/src/main/java/com/auth0/json/mgmt/ClientGrantsPageDeserializer.java +++ b/src/main/java/com/auth0/json/mgmt/clientgrants/ClientGrantsPageDeserializer.java @@ -1,4 +1,6 @@ -package com.auth0.json.mgmt; +package com.auth0.json.mgmt.clientgrants; + +import com.auth0.json.mgmt.PageDeserializer; import java.util.List; diff --git a/src/main/java/com/auth0/json/mgmt/connections/Clients.java b/src/main/java/com/auth0/json/mgmt/connections/Clients.java new file mode 100644 index 000000000..f0d5f0d02 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/connections/Clients.java @@ -0,0 +1,36 @@ +package com.auth0.json.mgmt.connections; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +public class Clients { + @JsonProperty("client_id") + private String clientId; + + /** + * Default constructor for the Clients class. + */ + public Clients() { + } + + /** + * Constructor for the Clients class. + * + * @param clientId the client ID. + */ + public Clients(String clientId) { + this.clientId = clientId; + } + + /** + * Getter for the client ID. + * + * @return the client ID. + */ + public String getClientId() { + return clientId; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/Connection.java b/src/main/java/com/auth0/json/mgmt/connections/Connection.java similarity index 74% rename from src/main/java/com/auth0/json/mgmt/Connection.java rename to src/main/java/com/auth0/json/mgmt/connections/Connection.java index 50667db3e..b40a3dc56 100644 --- a/src/main/java/com/auth0/json/mgmt/Connection.java +++ b/src/main/java/com/auth0/json/mgmt/connections/Connection.java @@ -1,4 +1,4 @@ -package com.auth0.json.mgmt; +package com.auth0.json.mgmt.connections; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @@ -34,6 +34,10 @@ public class Connection { private Map metadata; @JsonProperty("realms") private List realms; + @JsonProperty("show_as_button") + private Boolean showAsButton; + @JsonProperty("is_domain_connection") + private Boolean isDomainConnection; public Connection() { } @@ -116,6 +120,8 @@ public String getStrategy() { /** * Getter for the list of applications this connection is enabled for. + *

Deprecated: This field is deprecated and will be removed in future versions. + * Use `updateEnabledClients` and `getEnabledClients` methods instead for managing enabled clients * * @return the list of enabled applications. */ @@ -126,6 +132,8 @@ public List getEnabledClients() { /** * Setter for the list of applications this connection is enabled for. + *

Deprecated: This field is deprecated and will be removed in future versions. + * Use `updateEnabledClients` and `getEnabledClients` methods instead for managing enabled clients * * @param enabledClients the list of enabled applications to set. */ @@ -183,4 +191,42 @@ public List getRealms() { public void setRealms(List realms) { this.realms = realms; } + + /** + * Getter for the show as button flag. + * + * @return the show as button flag. + */ + @JsonProperty("show_as_button") + public Boolean isShowAsButton() { + return showAsButton; + } + + /** + * Setter for the show as button flag. + * + * @param showAsButton the show as button flag to set. + */ + @JsonProperty("show_as_button") + public void setShowAsButton(Boolean showAsButton) { + this.showAsButton = showAsButton; + } + + /** + * Getter for the domain connection flag. + * @return the domain connection flag. + */ + @JsonProperty("is_domain_connection") + public Boolean isDomainConnection() { + return isDomainConnection; + } + + /** + * Setter for the domain connection flag. + * @param domainConnection the domain connection flag to set. + */ + @JsonProperty("is_domain_connection") + public void setDomainConnection(Boolean domainConnection) { + this.isDomainConnection = domainConnection; + } } diff --git a/src/main/java/com/auth0/json/mgmt/connections/ConnectionKeys.java b/src/main/java/com/auth0/json/mgmt/connections/ConnectionKeys.java new file mode 100644 index 000000000..b1bca6e0f --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/connections/ConnectionKeys.java @@ -0,0 +1,218 @@ +package com.auth0.json.mgmt.connections; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ConnectionKeys { + @JsonProperty("kid") + private String kid; + + @JsonProperty("algorithm") + private String algorithm; + + @JsonProperty("key_use") + private String keyUse; + + @JsonProperty("subject_dn") + private String subjectDn; + + @JsonProperty("cert") + private String cert; + + @JsonProperty("fingerprint") + private String fingerprint; + + @JsonProperty("thumbprint") + private String thumbprint; + + @JsonProperty("pkcs") + private String pkcs; + + @JsonProperty("current") + private Boolean current; + + @JsonProperty("current_since") + private String currentSince; + + @JsonProperty("next") + private Boolean next; + + /** + * Getter for the Key ID (kid). + * @return the Key ID (kid). + */ + public String getKid() { + return kid; + } + + /** + * Setter for the Key ID (kid). + * @param kid the Key ID (kid). + */ + public void setKid(String kid) { + this.kid = kid; + } + + /** + * Getter for the algorithm used by the key. + * @return the algorithm used by the key. + */ + public String getAlgorithm() { + return algorithm; + } + + /** + * Setter for the algorithm used by the key. + * @param algorithm the algorithm used by the key. + */ + public void setAlgorithm(String algorithm) { + this.algorithm = algorithm; + } + + /** + * Getter for the key use (e.g., "sig" for signature). + * @return the key use. + */ + public String getKeyUse() { + return keyUse; + } + + /** + * Setter for the key use. + * @param keyUse the key use (e.g., "sig" for signature). + */ + public void setKeyUse(String keyUse) { + this.keyUse = keyUse; + } + + /** + * Getter for the subject distinguished name (DN). + * @return the subject DN. + */ + public String getSubjectDn() { + return subjectDn; + } + + /** + * Setter for the subject distinguished name (DN). + * @param subjectDn the subject DN. + */ + public void setSubjectDn(String subjectDn) { + this.subjectDn = subjectDn; + } + + /** + * Getter for the certificate associated with the key. + * @return the certificate. + */ + public String getCert() { + return cert; + } + + /** + * Setter for the certificate associated with the key. + * @param cert the certificate. + */ + public void setCert(String cert) { + this.cert = cert; + } + + /** + * Getter for the fingerprint of the key. + * @return the fingerprint. + */ + public String getFingerprint() { + return fingerprint; + } + + /** + * Setter for the fingerprint of the key. + * @param fingerprint the fingerprint. + */ + public void setFingerprint(String fingerprint) { + this.fingerprint = fingerprint; + } + + /** + * Getter for the thumbprint of the key. + * @return the thumbprint. + */ + public String getThumbprint() { + return thumbprint; + } + + /** + * Setter for the thumbprint of the key. + * @param thumbprint the thumbprint. + */ + public void setThumbprint(String thumbprint) { + this.thumbprint = thumbprint; + } + + /** + * Getter for the PKCS#8 representation of the key. + * @return the PKCS#8 representation. + */ + public String getPkcs() { + return pkcs; + } + + /** + * Setter for the PKCS#8 representation of the key. + * @param pkcs the PKCS#8 representation. + */ + public void setPkcs(String pkcs) { + this.pkcs = pkcs; + } + + /** + * Getter for whether the key is currently active. + * @return true if the key is current, false otherwise. + */ + public Boolean getCurrent() { + return current; + } + + /** + * Setter for whether the key is currently active. + * @param current true if the key is current, false otherwise. + */ + public void setCurrent(Boolean current) { + this.current = current; + } + + /** + * Getter for the timestamp when the key became current. + * @return the timestamp in ISO 8601 format. + */ + public String getCurrentSince() { + return currentSince; + } + + /** + * Setter for the timestamp when the key became current. + * @param currentSince the timestamp in ISO 8601 format. + */ + public void setCurrentSince(String currentSince) { + this.currentSince = currentSince; + } + + /** + * Getter for whether there is a next key available. + * @return true if there is a next key, false otherwise. + */ + public Boolean getNext() { + return next; + } + + /** + * Setter for whether there is a next key available. + * @param next true if there is a next key, false otherwise. + */ + public void setNext(Boolean next) { + this.next = next; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/ConnectionsPage.java b/src/main/java/com/auth0/json/mgmt/connections/ConnectionsPage.java similarity index 75% rename from src/main/java/com/auth0/json/mgmt/ConnectionsPage.java rename to src/main/java/com/auth0/json/mgmt/connections/ConnectionsPage.java index caf913f7c..dfb663239 100644 --- a/src/main/java/com/auth0/json/mgmt/ConnectionsPage.java +++ b/src/main/java/com/auth0/json/mgmt/connections/ConnectionsPage.java @@ -1,5 +1,6 @@ -package com.auth0.json.mgmt; +package com.auth0.json.mgmt.connections; +import com.auth0.json.mgmt.Page; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; @@ -23,4 +24,8 @@ public ConnectionsPage(Integer start, Integer length, Integer total, Integer lim super(start, length, total, limit, items); } -} \ No newline at end of file + public ConnectionsPage(Integer start, Integer length, Integer total, Integer limit, String next, List items){ + super(start, length, total, limit, next, items); + } + +} diff --git a/src/main/java/com/auth0/json/mgmt/ConnectionsPageDeserializer.java b/src/main/java/com/auth0/json/mgmt/connections/ConnectionsPageDeserializer.java similarity index 71% rename from src/main/java/com/auth0/json/mgmt/ConnectionsPageDeserializer.java rename to src/main/java/com/auth0/json/mgmt/connections/ConnectionsPageDeserializer.java index 39bcd08c1..52b616af1 100644 --- a/src/main/java/com/auth0/json/mgmt/ConnectionsPageDeserializer.java +++ b/src/main/java/com/auth0/json/mgmt/connections/ConnectionsPageDeserializer.java @@ -1,4 +1,6 @@ -package com.auth0.json.mgmt; +package com.auth0.json.mgmt.connections; + +import com.auth0.json.mgmt.PageDeserializer; import java.util.List; @@ -27,4 +29,9 @@ protected ConnectionsPage createPage(Integer start, Integer length, Integer tota return new ConnectionsPage(start, length, total, limit, items); } + @Override + protected ConnectionsPage createPage(Integer start, Integer length, Integer total, Integer limit, String next, List items) { + return new ConnectionsPage(start, length, total, limit, next, items); + } + } diff --git a/src/main/java/com/auth0/json/mgmt/connections/DefaultScimMappingResponse.java b/src/main/java/com/auth0/json/mgmt/connections/DefaultScimMappingResponse.java new file mode 100644 index 000000000..481e7df75 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/connections/DefaultScimMappingResponse.java @@ -0,0 +1,47 @@ +package com.auth0.json.mgmt.connections; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class DefaultScimMappingResponse { + @JsonProperty("mapping") + private List mapping; + + /** + * Creates a new instance. + */ + @JsonCreator + public DefaultScimMappingResponse() { + } + + /** + * Creates a new instance with the given mapping. + * @param mapping the mapping attribute. + */ + @JsonCreator + public DefaultScimMappingResponse(@JsonProperty("mapping") List mapping) { + this.mapping = mapping; + } + + /** + * Getter for the mapping attribute. + * @return the mapping attribute. + */ + public List getMapping() { + return mapping; + } + + /** + * Setter for the mapping attribute. + * @param mapping the mapping attribute to set. + */ + public void setMapping(List mapping) { + this.mapping = mapping; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/connections/EnabledClientRequest.java b/src/main/java/com/auth0/json/mgmt/connections/EnabledClientRequest.java new file mode 100644 index 000000000..5845b652e --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/connections/EnabledClientRequest.java @@ -0,0 +1,44 @@ +package com.auth0.json.mgmt.connections; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +public class EnabledClientRequest { + @JsonProperty("client_id") + private String clientId; + + @JsonProperty("status") + private boolean status; + + /** + * Constructor for the EnabledClientRequest. + * @param clientId + * @param status + */ + public EnabledClientRequest(String clientId, boolean status) { + this.clientId = clientId; + this.status = status; + } + + /** + * Getter for the client ID. + * + * @return the client ID. + */ + public String getClientId() { + return clientId; + } + + /** + * Getter for the status. + * + * @return the status. + */ + @JsonProperty("status") + public boolean isStatus() { + return status; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/connections/EnabledClientResponse.java b/src/main/java/com/auth0/json/mgmt/connections/EnabledClientResponse.java new file mode 100644 index 000000000..c139d95ab --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/connections/EnabledClientResponse.java @@ -0,0 +1,52 @@ +package com.auth0.json.mgmt.connections; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +public class EnabledClientResponse { + @JsonProperty("clients") + private List clients; + @JsonProperty("next") + private String next; + + /** + * Getter for the list of clients. + * + * @return the list of clients. + */ + public List getClients() { + return clients; + } + + /** + * Setter for the list of clients. + * + * @param clients the list of clients to set. + */ + public void setClients(List clients) { + this.clients = clients; + } + + /** + * Getter for the next page URL. + * + * @return the next page URL. + */ + public String getNext() { + return next; + } + + /** + * Setter for the next page URL. + * + * @param next the next page URL to set. + */ + public void setNext(String next) { + this.next = next; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/connections/Mapping.java b/src/main/java/com/auth0/json/mgmt/connections/Mapping.java new file mode 100644 index 000000000..868c6e7d8 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/connections/Mapping.java @@ -0,0 +1,66 @@ +package com.auth0.json.mgmt.connections; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class Mapping { + @JsonProperty("auth0") + private String auth0; + @JsonProperty("scim") + private String scim; + + /** + * Creates a new instance. + */ + @JsonCreator + public Mapping() { + + } + + /** + * Creates a new instance with the given Auth0 and SCIM attributes. + * @param auth0 the Auth0 attribute. + * @param scim the SCIM attribute. + */ + @JsonCreator + public Mapping(@JsonProperty("auth0") String auth0, @JsonProperty("scim") String scim) { + this.auth0 = auth0; + this.scim = scim; + } + + /** + * Getter for the Auth0 attribute. + * @return the Auth0 attribute. + */ + public String getAuth0() { + return auth0; + } + + /** + * Setter for the Auth0 attribute. + * @param auth0 the Auth0 attribute to set. + */ + public void setAuth0(String auth0) { + this.auth0 = auth0; + } + + /** + * Getter for the SCIM attribute. + * @return the SCIM attribute. + */ + public String getScim() { + return scim; + } + + /** + * Setter for the SCIM attribute. + * @param scim the SCIM attribute to set. + */ + public void setScim(String scim) { + this.scim = scim; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/connections/RotateKey.java b/src/main/java/com/auth0/json/mgmt/connections/RotateKey.java new file mode 100644 index 000000000..d83bc656a --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/connections/RotateKey.java @@ -0,0 +1,46 @@ +package com.auth0.json.mgmt.connections; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class RotateKey { + @JsonProperty("cert") + private String cert; + @JsonProperty("kid") + private String kid; + + /** + * Returns the certificate used for the key rotation. + * @return the certificate as a String. + */ + public String getCert() { + return cert; + } + + /** + * Sets the certificate used for the key rotation. + * @param cert the certificate as a String. + */ + public void setCert(String cert) { + this.cert = cert; + } + + /** + * Returns the Key ID (kid) of the key being rotated. + * @return the Key ID as a String. + */ + public String getKid() { + return kid; + } + + /** + * Sets the Key ID (kid) of the key being rotated. + * @param kid the Key ID as a String. + */ + public void setKid(String kid) { + this.kid = kid; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/connections/ScimConfigurationRequest.java b/src/main/java/com/auth0/json/mgmt/connections/ScimConfigurationRequest.java new file mode 100644 index 000000000..337d5288b --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/connections/ScimConfigurationRequest.java @@ -0,0 +1,65 @@ +package com.auth0.json.mgmt.connections; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +public class ScimConfigurationRequest { + @JsonProperty("user_id_attribute") + private String userIdAttribute; + @JsonProperty("mapping") + private List mapping; + + /** + * Creates a new instance. + */ + public ScimConfigurationRequest() { + + } + + /** + * Creates a new instance with the given user id attribute and mapping. + * @param userIdAttribute the user id attribute. + * @param mapping the mappings. + */ + public ScimConfigurationRequest(String userIdAttribute, List mapping) { + this.userIdAttribute = userIdAttribute; + this.mapping = mapping; + } + + /** + * Getter for the user id attribute. + * @return the user id attribute. + */ + public String getUserIdAttribute() { + return userIdAttribute; + } + + /** + * Setter for the user id attribute. + * @param userIdAttribute the user id attribute to set. + */ + public void setUserIdAttribute(String userIdAttribute) { + this.userIdAttribute = userIdAttribute; + } + + /** + * Getter for the mapping. + * @return the mapping. + */ + public List getMapping() { + return mapping; + } + + /** + * Setter for the mapping. + * @param mapping the mapping to set. + */ + public void setMapping(List mapping) { + this.mapping = mapping; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/connections/ScimConfigurationResponse.java b/src/main/java/com/auth0/json/mgmt/connections/ScimConfigurationResponse.java new file mode 100644 index 000000000..1133fa590 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/connections/ScimConfigurationResponse.java @@ -0,0 +1,156 @@ +package com.auth0.json.mgmt.connections; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +public class ScimConfigurationResponse { + @JsonProperty("connection_id") + private String connectionId; + @JsonProperty("connection_name") + private String connectionName; + @JsonProperty("strategy") + private String strategy; + @JsonProperty("tenant_name") + private String tenantName; + @JsonProperty("user_id_attribute") + private String userIdAttribute; + @JsonProperty("mapping") + private List mapping; + @JsonProperty("created_at") + private String createdAt; + @JsonProperty("updated_on") + private String updatedOn; + + /** + * Getter for the connection id. + * @return the connection id. + */ + public String getConnectionId() { + return connectionId; + } + + /** + * Setter for the connection id. + * @param connectionId the connection id to set. + */ + public void setConnectionId(String connectionId) { + this.connectionId = connectionId; + } + + /** + * Getter for the connection name. + * @return the connection name. + */ + public String getConnectionName() { + return connectionName; + } + + /** + * Setter for the connection name. + * @param connectionName the connection name to set. + */ + public void setConnectionName(String connectionName) { + this.connectionName = connectionName; + } + + /** + * Getter for the strategy. + * @return the strategy. + */ + public String getStrategy() { + return strategy; + } + + /** + * Setter for the strategy. + * @param strategy the strategy to set. + */ + public void setStrategy(String strategy) { + this.strategy = strategy; + } + + /** + * Getter for the tenant name. + * @return the tenant name. + */ + public String getTenantName() { + return tenantName; + } + + /** + * Setter for the tenant name. + * @param tenantName the tenant name to set. + */ + public void setTenantName(String tenantName) { + this.tenantName = tenantName; + } + + /** + * Getter for the user id attribute. + * @return the user id attribute. + */ + public String getUserIdAttribute() { + return userIdAttribute; + } + + /** + * Setter for the user id attribute. + * @param userIdAttribute the user id attribute to set. + */ + public void setUserIdAttribute(String userIdAttribute) { + this.userIdAttribute = userIdAttribute; + } + + /** + * Getter for the mapping. + * @return the mapping. + */ + public List getMapping() { + return mapping; + } + + /** + * Setter for the mapping. + * @param mapping the mapping to set. + */ + public void setMapping(List mapping) { + this.mapping = mapping; + } + + /** + * Getter for the created at. + * @return the created at. + */ + public String getCreatedAt() { + return createdAt; + } + + /** + * Setter for the created at. + * @param createdAt the created at to set. + */ + public void setCreatedAt(String createdAt) { + this.createdAt = createdAt; + } + + /** + * Getter for the updated on. + * @return the updated on. + */ + public String getUpdatedOn() { + return updatedOn; + } + + /** + * Setter for the updated on. + * @param updatedOn the updated on to set. + */ + public void setUpdatedOn(String updatedOn) { + this.updatedOn = updatedOn; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/connections/ScimTokenBaseResponse.java b/src/main/java/com/auth0/json/mgmt/connections/ScimTokenBaseResponse.java new file mode 100644 index 000000000..951461054 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/connections/ScimTokenBaseResponse.java @@ -0,0 +1,84 @@ +package com.auth0.json.mgmt.connections; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ScimTokenBaseResponse { + @JsonProperty("token_id") + private String tokenId; + @JsonProperty("scopes") + private List scopes; + @JsonProperty("created_at") + private String createdAt; + @JsonProperty("valid_until") + private String validUntil; + + /** + * Getter for the token id. + * @return the token id. + */ + public String getTokenId() { + return tokenId; + } + + /** + * Setter for the token id. + * @param tokenId the token id to set. + */ + public void setTokenId(String tokenId) { + this.tokenId = tokenId; + } + + /** + * Getter for the scopes. + * @return the scopes. + */ + public List getScopes() { + return scopes; + } + + /** + * Setter for the scopes. + * @param scopes the scopes to set. + */ + public void setScopes(List scopes) { + this.scopes = scopes; + } + + /** + * Getter for the created at. + * @return the created at. + */ + public String getCreatedAt() { + return createdAt; + } + + /** + * Setter for the created at. + * @param createdAt the created at to set. + */ + public void setCreatedAt(String createdAt) { + this.createdAt = createdAt; + } + + /** + * Getter for the valid until. + * @return the valid until. + */ + public String getValidUntil() { + return validUntil; + } + + /** + * Setter for the valid until. + * @param validUntil the valid until to set. + */ + public void setValidUntil(String validUntil) { + this.validUntil = validUntil; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/connections/ScimTokenCreateResponse.java b/src/main/java/com/auth0/json/mgmt/connections/ScimTokenCreateResponse.java new file mode 100644 index 000000000..ce332e0be --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/connections/ScimTokenCreateResponse.java @@ -0,0 +1,28 @@ +package com.auth0.json.mgmt.connections; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +public class ScimTokenCreateResponse extends ScimTokenBaseResponse { + @JsonProperty("token") + private String token; + + /** + * Getter for the token. + * @return the token. + */ + public String getToken() { + return token; + } + + /** + * Setter for the token. + * @param token the token to set. + */ + public void setToken(String token) { + this.token = token; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/connections/ScimTokenRequest.java b/src/main/java/com/auth0/json/mgmt/connections/ScimTokenRequest.java new file mode 100644 index 000000000..3d2d387b8 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/connections/ScimTokenRequest.java @@ -0,0 +1,48 @@ +package com.auth0.json.mgmt.connections; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ScimTokenRequest { + @JsonProperty("scopes") + private List scopes; + @JsonProperty("token_lifetime") + private Integer tokenLifetime; + + /** + * Getter for the scopes. + * @return the scopes. + */ + public List getScopes() { + return scopes; + } + + /** + * Setter for the scopes. + * @param scopes the scopes to set. + */ + public void setScopes(List scopes) { + this.scopes = scopes; + } + + /** + * Getter for the token lifetime. + * @return the token lifetime. + */ + public Integer getTokenLifetime() { + return tokenLifetime; + } + + /** + * Setter for the token lifetime. + * @param tokenLifetime the token lifetime to set. + */ + public void setTokenLifetime(Integer tokenLifetime) { + this.tokenLifetime = tokenLifetime; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/connections/ScimTokenResponse.java b/src/main/java/com/auth0/json/mgmt/connections/ScimTokenResponse.java new file mode 100644 index 000000000..1cbea6390 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/connections/ScimTokenResponse.java @@ -0,0 +1,28 @@ +package com.auth0.json.mgmt.connections; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ScimTokenResponse extends ScimTokenBaseResponse { + @JsonProperty("last_used_at") + private String lastUsedAt; + + /** + * Getter for the last used at. + * @return the last used at. + */ + public String getLastUsedAt() { + return lastUsedAt; + } + + /** + * Setter for the last used at. + * @param lastUsedAt the last used at to set. + */ + public void setLastUsedAt(String lastUsedAt) { + this.lastUsedAt = lastUsedAt; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/DeviceCredentials.java b/src/main/java/com/auth0/json/mgmt/devicecredentials/DeviceCredentials.java similarity index 98% rename from src/main/java/com/auth0/json/mgmt/DeviceCredentials.java rename to src/main/java/com/auth0/json/mgmt/devicecredentials/DeviceCredentials.java index 260c19684..2fd9b19d0 100644 --- a/src/main/java/com/auth0/json/mgmt/DeviceCredentials.java +++ b/src/main/java/com/auth0/json/mgmt/devicecredentials/DeviceCredentials.java @@ -1,4 +1,4 @@ -package com.auth0.json.mgmt; +package com.auth0.json.mgmt.devicecredentials; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; diff --git a/src/main/java/com/auth0/json/mgmt/EmailTemplate.java b/src/main/java/com/auth0/json/mgmt/emailtemplates/EmailTemplate.java similarity index 99% rename from src/main/java/com/auth0/json/mgmt/EmailTemplate.java rename to src/main/java/com/auth0/json/mgmt/emailtemplates/EmailTemplate.java index a72a5d09b..6fc46b3f1 100644 --- a/src/main/java/com/auth0/json/mgmt/EmailTemplate.java +++ b/src/main/java/com/auth0/json/mgmt/emailtemplates/EmailTemplate.java @@ -1,4 +1,4 @@ -package com.auth0.json.mgmt; +package com.auth0.json.mgmt.emailtemplates; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; diff --git a/src/main/java/com/auth0/json/mgmt/Grant.java b/src/main/java/com/auth0/json/mgmt/grants/Grant.java similarity index 98% rename from src/main/java/com/auth0/json/mgmt/Grant.java rename to src/main/java/com/auth0/json/mgmt/grants/Grant.java index 3ffbd0038..e7365d9fa 100644 --- a/src/main/java/com/auth0/json/mgmt/Grant.java +++ b/src/main/java/com/auth0/json/mgmt/grants/Grant.java @@ -1,4 +1,4 @@ -package com.auth0.json.mgmt; +package com.auth0.json.mgmt.grants; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; diff --git a/src/main/java/com/auth0/json/mgmt/GrantsPage.java b/src/main/java/com/auth0/json/mgmt/grants/GrantsPage.java similarity index 91% rename from src/main/java/com/auth0/json/mgmt/GrantsPage.java rename to src/main/java/com/auth0/json/mgmt/grants/GrantsPage.java index 6b23fe4bd..39d2dce92 100644 --- a/src/main/java/com/auth0/json/mgmt/GrantsPage.java +++ b/src/main/java/com/auth0/json/mgmt/grants/GrantsPage.java @@ -1,5 +1,6 @@ -package com.auth0.json.mgmt; +package com.auth0.json.mgmt.grants; +import com.auth0.json.mgmt.Page; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; @@ -23,4 +24,4 @@ public GrantsPage(Integer start, Integer length, Integer total, Integer limit, L super(start, length, total, limit, items); } -} \ No newline at end of file +} diff --git a/src/main/java/com/auth0/json/mgmt/GrantsPageDeserializer.java b/src/main/java/com/auth0/json/mgmt/grants/GrantsPageDeserializer.java similarity index 90% rename from src/main/java/com/auth0/json/mgmt/GrantsPageDeserializer.java rename to src/main/java/com/auth0/json/mgmt/grants/GrantsPageDeserializer.java index 3dd91fcd3..4d9fb9012 100644 --- a/src/main/java/com/auth0/json/mgmt/GrantsPageDeserializer.java +++ b/src/main/java/com/auth0/json/mgmt/grants/GrantsPageDeserializer.java @@ -1,4 +1,6 @@ -package com.auth0.json.mgmt; +package com.auth0.json.mgmt.grants; + +import com.auth0.json.mgmt.PageDeserializer; import java.util.List; diff --git a/src/main/java/com/auth0/json/mgmt/guardian/EnrollmentTicket.java b/src/main/java/com/auth0/json/mgmt/guardian/EnrollmentTicket.java index 79d4c7361..d36c7afbe 100644 --- a/src/main/java/com/auth0/json/mgmt/guardian/EnrollmentTicket.java +++ b/src/main/java/com/auth0/json/mgmt/guardian/EnrollmentTicket.java @@ -74,18 +74,6 @@ public String getUserId() { return userId; } - /** - * Setter for the id of the user this ticket is meant to. - * - * @param userId the user id to set. - * @deprecated use the constructor instead - */ - @Deprecated - @JsonProperty("user_id") - public void setUserId(String userId) { - this.userId = userId; - } - /** * Whether to send and email for enrollment or not. * @@ -96,18 +84,6 @@ public Boolean willSendEmail() { return sendEmail; } - /** - * Sets whether to send and email for enrollment or not. - * - * @param sendEmail whether this ticket will send an email upon enrollment or not. - * @deprecated use the constructor instead - */ - @Deprecated - @JsonProperty("send_mail") - public void setSendEmail(Boolean sendEmail) { - this.sendEmail = sendEmail; - } - /** * Getter for the email to which the ticket will be sent. * @@ -118,18 +94,6 @@ public String getEmail() { return email; } - /** - * Setter for the email to which the ticket will be sent. - * - * @param email the email to sent the ticket to. - * @deprecated use the constructor instead - */ - @Deprecated - @JsonProperty("email") - public void setEmail(String email) { - this.email = email; - } - /** * Getter for the ticket id. * diff --git a/src/main/java/com/auth0/json/mgmt/guardian/SNSFactorProvider.java b/src/main/java/com/auth0/json/mgmt/guardian/SNSFactorProvider.java index 88459b69c..47772125f 100644 --- a/src/main/java/com/auth0/json/mgmt/guardian/SNSFactorProvider.java +++ b/src/main/java/com/auth0/json/mgmt/guardian/SNSFactorProvider.java @@ -25,15 +25,6 @@ public class SNSFactorProvider { @JsonProperty("sns_gcm_platform_application_arn") private String snsGCMPlatformApplicationArn; - /** - * Creates an empty SNS settings object - * - * @deprecated use the full constructor instead - */ - @Deprecated - public SNSFactorProvider() { - } - /** * Creates a SNS settings object * @@ -62,18 +53,6 @@ public String getAWSAccessKeyId() { return awsAccessKeyId; } - /** - * Setter for the Amazon Web Services access key id. - * - * @param awsAccessKeyId the AWS access key id to set. - * @deprecated use the constructor instead - */ - @Deprecated - @JsonProperty("aws_access_key_id") - public void setAWSAccessKeyId(String awsAccessKeyId) { - this.awsAccessKeyId = awsAccessKeyId; - } - /** * Getter for the Amazon Web Services secret access key. * @@ -84,18 +63,6 @@ public String getAWSSecretAccessKey() { return awsSecretAccessKey; } - /** - * Setter for the Amazon Web Services secret access key. - * - * @param awsSecretAccessKey the AWS secret access key to set. - * @deprecated use the constructor instead - */ - @Deprecated - @JsonProperty("aws_secret_access_key") - public void setAWSSecretAccessKey(String awsSecretAccessKey) { - this.awsSecretAccessKey = awsSecretAccessKey; - } - /** * Getter for the Amazon Web Services region. * @@ -106,18 +73,6 @@ public String getAWSRegion() { return awsRegion; } - /** - * Setter for the Amazon Web Services region. - * - * @param awsRegion the AWS region to set. - * @deprecated use the constructor instead - */ - @Deprecated - @JsonProperty("aws_region") - public void setAWSRegion(String awsRegion) { - this.awsRegion = awsRegion; - } - /** * Getter for the Simple Notification Service Apple Push Notification service platform application Amazon Resource Name. * @@ -128,18 +83,6 @@ public String getSNSAPNSPlatformApplicationARN() { return snsAPNSPlatformApplicationArn; } - /** - * Setter for the Simple Notification Service Apple Push Notification service platform application Amazon Resource Name. - * - * @param apnARN the SNS APNs ARN to set. - * @deprecated use the constructor instead - */ - @Deprecated - @JsonProperty("sns_apns_platform_application_arn") - public void setSNSAPNSPlatformApplicationARN(String apnARN) { - this.snsAPNSPlatformApplicationArn = apnARN; - } - /** * Getter for the Simple Notification Service Google Cloud Messaging platform application Amazon Resource Name. * @@ -150,15 +93,4 @@ public String getSNSGCMPlatformApplicationARN() { return snsGCMPlatformApplicationArn; } - /** - * Setter for the Simple Notification Service Google Cloud Messaging platform application Amazon Resource Name. - * - * @param gcmARN the SNS GCM ARN to set. - * @deprecated use the constructor instead - */ - @Deprecated - @JsonProperty("sns_gcm_platform_application_arn") - public void setSNSGCMPlatformApplicationARN(String gcmARN) { - this.snsGCMPlatformApplicationArn = gcmARN; - } } diff --git a/src/main/java/com/auth0/json/mgmt/guardian/TwilioFactorProvider.java b/src/main/java/com/auth0/json/mgmt/guardian/TwilioFactorProvider.java index cfbb93fbb..3fca3ab9c 100644 --- a/src/main/java/com/auth0/json/mgmt/guardian/TwilioFactorProvider.java +++ b/src/main/java/com/auth0/json/mgmt/guardian/TwilioFactorProvider.java @@ -23,15 +23,6 @@ public class TwilioFactorProvider { @JsonProperty("sid") private String sid; - /** - * Creates an empty Twilio settings object - * - * @deprecated use the full constructor instead - */ - @Deprecated - public TwilioFactorProvider() { - } - /** * Creates a Twilio settings object * @@ -65,22 +56,6 @@ public String getFrom() { return from; } - /** - * Setter for the Twilio From number. - * - * @param from the from number to set. - * @throws IllegalArgumentException when both `from` and `messagingServiceSID` are set - * @deprecated use the constructor instead - */ - @Deprecated - @JsonProperty("from") - public void setFrom(String from) throws IllegalArgumentException { - if (messagingServiceSID != null) { - throw new IllegalArgumentException("You must specify either `from` or `messagingServiceSID`, but not both"); - } - this.from = from; - } - /** * Getter for the Twilio Messaging Service SID. * @@ -91,22 +66,6 @@ public String getMessagingServiceSID() { return messagingServiceSID; } - /** - * Setter for the Twilio Messaging Service SID. - * - * @param messagingServiceSID the messaging service SID. - * @throws IllegalArgumentException when both `from` and `messagingServiceSID` are set - * @deprecated use the constructor instead - */ - @Deprecated - @JsonProperty("messaging_service_sid") - public void setMessagingServiceSID(String messagingServiceSID) throws IllegalArgumentException { - if (from != null) { - throw new IllegalArgumentException("You must specify either `from` or `messagingServiceSID`, but not both"); - } - this.messagingServiceSID = messagingServiceSID; - } - /** * Getter for the Twilio auth token. * @@ -117,18 +76,6 @@ public String getAuthToken() { return authToken; } - /** - * Setter for the Twilio auth token. - * - * @param authToken the Twilio auth token to set. - * @deprecated use the constructor instead - */ - @Deprecated - @JsonProperty("auth_token") - public void setAuthToken(String authToken) { - this.authToken = authToken; - } - /** * Getter for the Twilio SID * @@ -139,15 +86,4 @@ public String getSID() { return sid; } - /** - * Setter for the Twilio SID - * - * @param SID the Twilio SID to set. - * @deprecated use the constructor instead - */ - @Deprecated - @JsonProperty("sid") - public void setSID(String SID) { - this.sid = SID; - } } diff --git a/src/main/java/com/auth0/json/mgmt/keys/EncryptionKey.java b/src/main/java/com/auth0/json/mgmt/keys/EncryptionKey.java new file mode 100644 index 000000000..00f52fe12 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/keys/EncryptionKey.java @@ -0,0 +1,136 @@ +package com.auth0.json.mgmt.keys; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class EncryptionKey { + @JsonProperty("kid") + private String kid; + @JsonProperty("type") + private String type; + @JsonProperty("state") + private String state; + @JsonProperty("created_at") + private String createdAt; + @JsonProperty("updated_at") + private String updatedAt; + @JsonProperty("parent_kid") + private String parentKid; + @JsonProperty("public_key") + private String publicKey; + + /** + * Getter for the key id. + * @return + */ + public String getKid() { + return kid; + } + + /** + * Setter for the key id. + * @param kid + */ + public void setKid(String kid) { + this.kid = kid; + } + + /** + * Getter for the key type. + * @return + */ + public String getType() { + return type; + } + + /** + * Setter for the key type. + * @param type + */ + public void setType(String type) { + this.type = type; + } + + /** + * Getter for the key state. + * @return + */ + public String getState() { + return state; + } + + /** + * Setter for the key state. + * @param state + */ + public void setState(String state) { + this.state = state; + } + + /** + * Getter for the key creation date. + * @return + */ + public String getCreatedAt() { + return createdAt; + } + + /** + * Setter for the key creation date. + * @param createdAt + */ + public void setCreatedAt(String createdAt) { + this.createdAt = createdAt; + } + + /** + * Getter for the key update date. + * @return + */ + public String getUpdatedAt() { + return updatedAt; + } + + /** + * Setter for the key update date. + * @param updatedAt + */ + public void setUpdatedAt(String updatedAt) { + this.updatedAt = updatedAt; + } + + /** + * Getter for the parent key id. + * @return + */ + public String getParentKid() { + return parentKid; + } + + /** + * Setter for the parent key id. + * @param parentKid + */ + public void setParentKid(String parentKid) { + this.parentKid = parentKid; + } + + /** + * Getter for the public key. + * @return + */ + public String getPublicKey() { + return publicKey; + } + + /** + * Setter for the public key. + * @param publicKey + */ + public void setPublicKey(String publicKey) { + this.publicKey = publicKey; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/keys/EncryptionKeysPage.java b/src/main/java/com/auth0/json/mgmt/keys/EncryptionKeysPage.java new file mode 100644 index 000000000..283a5aa31 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/keys/EncryptionKeysPage.java @@ -0,0 +1,24 @@ +package com.auth0.json.mgmt.keys; + +import com.auth0.json.mgmt.Page; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; + +import java.util.List; + +@SuppressWarnings({"unused", "WeakerAccess"}) +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonDeserialize(using = EncryptionKeysPageDeserializer.class) +public class EncryptionKeysPage extends Page { + + public EncryptionKeysPage(List items) { + super(items); + } + + public EncryptionKeysPage(Integer start, Integer length, Integer total, Integer limit, List items) { + super(start, length, total, limit, items); + } + +} diff --git a/src/main/java/com/auth0/json/mgmt/keys/EncryptionKeysPageDeserializer.java b/src/main/java/com/auth0/json/mgmt/keys/EncryptionKeysPageDeserializer.java new file mode 100644 index 000000000..797255e1f --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/keys/EncryptionKeysPageDeserializer.java @@ -0,0 +1,23 @@ +package com.auth0.json.mgmt.keys; + +import com.auth0.json.mgmt.PageDeserializer; + +import java.util.List; + +public class EncryptionKeysPageDeserializer extends PageDeserializer { + + protected EncryptionKeysPageDeserializer() { + super(EncryptionKey.class, "keys"); + } + + @Override + protected EncryptionKeysPage createPage(List items) { + return new EncryptionKeysPage(items); + } + + @Override + protected EncryptionKeysPage createPage(Integer start, Integer length, Integer total, Integer limit, List items) { + return new EncryptionKeysPage(start, length, total, limit, items); + } + +} diff --git a/src/main/java/com/auth0/json/mgmt/keys/EncryptionWrappingKeyResponse.java b/src/main/java/com/auth0/json/mgmt/keys/EncryptionWrappingKeyResponse.java new file mode 100644 index 000000000..49de28690 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/keys/EncryptionWrappingKeyResponse.java @@ -0,0 +1,46 @@ +package com.auth0.json.mgmt.keys; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class EncryptionWrappingKeyResponse { + @JsonProperty("public_key") + private String publicKey; + @JsonProperty("algorithm") + private String algorithm; + + /** + * Getter for the public key. + * @return the public key. + */ + public String getPublicKey() { + return publicKey; + } + + /** + * Setter for the public key. + * @param publicKey the public key. + */ + public void setPublicKey(String publicKey) { + this.publicKey = publicKey; + } + + /** + * Getter for the algorithm. + * @return the algorithm. + */ + public String getAlgorithm() { + return algorithm; + } + + /** + * Setter for the algorithm. + * @param algorithm the algorithm. + */ + public void setAlgorithm(String algorithm) { + this.algorithm = algorithm; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/Key.java b/src/main/java/com/auth0/json/mgmt/keys/Key.java similarity index 99% rename from src/main/java/com/auth0/json/mgmt/Key.java rename to src/main/java/com/auth0/json/mgmt/keys/Key.java index 08e05755b..c9adaa6f4 100644 --- a/src/main/java/com/auth0/json/mgmt/Key.java +++ b/src/main/java/com/auth0/json/mgmt/keys/Key.java @@ -1,4 +1,4 @@ -package com.auth0.json.mgmt; +package com.auth0.json.mgmt.keys; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; diff --git a/src/main/java/com/auth0/json/mgmt/logevents/LogEvent.java b/src/main/java/com/auth0/json/mgmt/logevents/LogEvent.java index f495fdb85..5d679a6cd 100644 --- a/src/main/java/com/auth0/json/mgmt/logevents/LogEvent.java +++ b/src/main/java/com/auth0/json/mgmt/logevents/LogEvent.java @@ -6,6 +6,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Date; +import java.util.List; import java.util.Map; /** @@ -39,6 +40,34 @@ public class LogEvent { private Map locationInfo; @JsonProperty("details") private Map details; + @JsonProperty("connection") + private String connection; + @JsonProperty("connection_id") + private String connectionId; + @JsonProperty("description") + private String description; + @JsonProperty("hostname") + private String hostname; + @JsonProperty("audience") + private String audience; + @JsonProperty("scope") + private Object scope; + @JsonProperty("strategy") + private String strategy; + @JsonProperty("strategy_type") + private String strategyType; + @JsonProperty("isMobile") + private boolean isMobile; + @JsonProperty("user_agent") + private String userAgent; + @JsonProperty("organization_id") + private String organizationId; + @JsonProperty("organization_name") + private String organizationName; + @JsonProperty("tenant_name") + private String tenantName; + @JsonProperty("$event_schema") + private Object eventSchema; /** * Getter for the id of this event. @@ -121,6 +150,51 @@ public String getUserId() { return userId; } + /** + * Getter for the scope of this event. + * @return the scope. + */ + @JsonProperty("scope") + public Object getScope() { + return scope; + } + + /** + * Getter for the strategy of this event. + * @return the strategy. + */ + @JsonProperty("strategy") + public String getStrategy() { + return strategy; + } + + /** + * Getter for the strategy type of this event. + * @return the strategy type. + */ + @JsonProperty("strategy_type") + public String getStrategyType() { + return strategyType; + } + + /** + * Getter for the isMobile flag of this event. + * @return the isMobile flag. + */ + @JsonProperty("isMobile") + public boolean isMobile() { + return isMobile; + } + + /** + * Getter for the user agent related to this event. + * @return the user agent. + */ + @JsonProperty("user_agent") + public String getUserAgent() { + return userAgent; + } + /** * Getter for the user name related to this event. * @@ -150,4 +224,68 @@ public Map getLocationInfo() { public Map getDetails() { return details; } + + /** + * @return the connection. + */ + public String getConnection() { + return connection; + } + + /** + * @return the connection ID + */ + public String getConnectionId() { + return connectionId; + } + + /** + * @return the description. + */ + public String getDescription() { + return description; + } + + /** + * @return the hostname. + */ + public String getHostname() { + return hostname; + } + + /** + * @return the audience. + */ + public String getAudience() { + return audience; + } + + /** + * @return the organization ID. + */ + public String getOrganizationId() { + return organizationId; + } + + /** + * @return the organization name. + */ + public String getOrganizationName() { + return organizationName; + } + + /** + * @return the tenant name. + */ + public String getTenantName() { + return tenantName; + } + + /** + * Getter for the event schema object. + * @return the event schema object. + */ + public Object getEventSchema() { + return eventSchema; + } } diff --git a/src/main/java/com/auth0/json/mgmt/logstreams/LogStream.java b/src/main/java/com/auth0/json/mgmt/logstreams/LogStream.java index 4fb9f157f..52b871726 100644 --- a/src/main/java/com/auth0/json/mgmt/logstreams/LogStream.java +++ b/src/main/java/com/auth0/json/mgmt/logstreams/LogStream.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.*; +import java.util.List; import java.util.Map; /** @@ -22,6 +23,9 @@ public class LogStream { @JsonProperty("sink") private Map sink; + @JsonProperty("filters") + private List filters; + /** * Creates a new LogStream instance and sets the type, which cannot be changed once set. * @@ -119,4 +123,22 @@ public Map getSink() { public void setSink(Map sink) { this.sink = sink; } + + /** + * @return the log stream filters + */ + @JsonProperty("filters") + public List getFilters() { + return filters; + } + + /** + * Set the log stream filters. + * + * @param filters the filters to set for the log stream. + */ + @JsonProperty("filters") + public void setFilters(List filters) { + this.filters = filters; + } } diff --git a/src/main/java/com/auth0/json/mgmt/logstreams/LogStreamFilter.java b/src/main/java/com/auth0/json/mgmt/logstreams/LogStreamFilter.java new file mode 100644 index 000000000..3e254c635 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/logstreams/LogStreamFilter.java @@ -0,0 +1,61 @@ +package com.auth0.json.mgmt.logstreams; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Represents an Auth0 Log Stream Filter object. Related to the {@linkplain com.auth0.client.mgmt.LogStreamsEntity} + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class LogStreamFilter { + + @JsonProperty("type") + private String type; + @JsonProperty("name") + private String name; + + /** + * Create a new instance. + * + * @param type the log stream filter type. + * @param name the log stream filter name. + */ + @JsonCreator + public LogStreamFilter(@JsonProperty("type") String type, @JsonProperty("name") String name) { + this.type = type; + this.name = name; + } + + /** + * @return the log stream filter type. + */ + @JsonProperty("type") + public String getType() { + return type; + } + + /** + * Set the log stream filter type. + * @param type the log stream filter type. + */ + @JsonProperty("type") + public void setType(String type) { + this.type = type; + } + + /** + * @return the log stream filter name. + */ + @JsonProperty("name") + public String getName() { + return name; + } + + @JsonProperty("name") + public void setName(String name) { + this.name = name; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/networkacls/Action.java b/src/main/java/com/auth0/json/mgmt/networkacls/Action.java new file mode 100644 index 000000000..029d86118 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/networkacls/Action.java @@ -0,0 +1,108 @@ +package com.auth0.json.mgmt.networkacls; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class Action { + @JsonProperty("block") + private Boolean block; + @JsonProperty("allow") + private Boolean allow; + @JsonProperty("log") + private Boolean log; + @JsonProperty("redirect") + private Boolean redirect; + @JsonProperty("redirect_uri") + private String redirectUri; + + /** + * Getter for the block action. + * @return true if the action is to block. + */ + @JsonProperty("block") + public Boolean isBlock() { + return block; + } + + /** + * Setter for the block action. + * @param block true to set the action as block, false otherwise. + */ + @JsonProperty("block") + public void setBlock(Boolean block) { + this.block = block; + } + + /** + * Getter for the allow action. + * @return true if the action is to allow. + */ + @JsonProperty("allow") + public Boolean isAllow() { + return allow; + } + + /** + * Setter for the allow action. + * @param allow true to set the action as allow, false otherwise. + */ + @JsonProperty("allow") + public void setAllow(Boolean allow) { + this.allow = allow; + } + + /** + * Getter for the log action. + * @return true if the action is to log. + */ + @JsonProperty("log") + public Boolean isLog() { + return log; + } + + /** + * Setter for the log action. + * @param log true to set the action as log, false otherwise. + */ + @JsonProperty("log") + public void setLog(Boolean log) { + this.log = log; + } + + /** + * Getter for the redirect action. + * @return true if the action is to redirect. + */ + @JsonProperty("redirect") + public Boolean isRedirect() { + return redirect; + } + + /** + * Setter for the redirect action. + * @param redirect true to set the action as redirect, false otherwise. + */ + @JsonProperty("redirect") + public void setRedirect(Boolean redirect) { + this.redirect = redirect; + } + + /** + * Getter for the redirect URI. + * @return the redirect URI if set, null otherwise. + */ + public String getRedrectUri() { + return redirectUri; + } + + /** + * Setter for the redirect URI. + * @param redrectUri the URI to set for redirection. + */ + public void setRedrectUri(String redrectUri) { + this.redirectUri = redrectUri; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/networkacls/Match.java b/src/main/java/com/auth0/json/mgmt/networkacls/Match.java new file mode 100644 index 000000000..dd8759eae --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/networkacls/Match.java @@ -0,0 +1,155 @@ +package com.auth0.json.mgmt.networkacls; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class Match { + private List asns; + @JsonProperty("geo_country_codes") + private List geoCountryCodes; + @JsonProperty("geo_subdivision_codes") + private List geoSubdivisionCodes; + @JsonProperty("ipv4_cidrs") + private List ipv4Cidrs; + @JsonProperty("ipv6_cidrs") + private List ipv6Cidrs; + @JsonProperty("ja3_fingerprints") + private List ja3Fingerprints; + @JsonProperty("ja4_fingerprints") + private List ja4Fingerprints; + @JsonProperty("user_agents") + private List userAgents; + + /** + * Getter for the ASNs. + * @return a list of ASNs. + */ + public List getAsns() { + return asns; + } + + /** + * Setter for the ASNs. + * @param asns a list of ASNs to set. + */ + public void setAsns(List asns) { + this.asns = asns; + } + + /** + * Getter for the geo country codes. + * @return a list of geo country codes. + */ + public List getGeoCountryCodes() { + return geoCountryCodes; + } + + /** + * Setter for the geo country codes. + * @param geoCountryCodes a list of geo country codes to set. + */ + public void setGeoCountryCodes(List geoCountryCodes) { + this.geoCountryCodes = geoCountryCodes; + } + + /** + * Getter for the geo subdivision codes. + * @return a list of geo subdivision codes. + */ + public List getGeoSubdivisionCodes() { + return geoSubdivisionCodes; + } + + /** + * Setter for the geo subdivision codes. + * @param geoSubdivisionCodes a list of geo subdivision codes to set. + */ + public void setGeoSubdivisionCodes(List geoSubdivisionCodes) { + this.geoSubdivisionCodes = geoSubdivisionCodes; + } + + /** + * Getter for the IPv4 CIDRs. + * @return a list of IPv4 CIDRs. + */ + public List getIpv4Cidrs() { + return ipv4Cidrs; + } + + /** + * Setter for the IPv4 CIDRs. + * @param ipv4Cidrs a list of IPv4 CIDRs to set. + */ + public void setIpv4Cidrs(List ipv4Cidrs) { + this.ipv4Cidrs = ipv4Cidrs; + } + + /** + * Getter for the IPv6 CIDRs. + * @return a list of IPv6 CIDRs. + */ + public List getIpv6Cidrs() { + return ipv6Cidrs; + } + + /** + * Setter for the IPv6 CIDRs. + * @param ipv6Cidrs a list of IPv6 CIDRs to set. + */ + public void setIpv6Cidrs(List ipv6Cidrs) { + this.ipv6Cidrs = ipv6Cidrs; + } + + /** + * Getter for the JA3 fingerprints. + * @return a list of JA3 fingerprints. + */ + public List getJa3Fingerprints() { + return ja3Fingerprints; + } + + /** + * Setter for the JA3 fingerprints. + * @param ja3Fingerprints a list of JA3 fingerprints to set. + */ + public void setJa3Fingerprints(List ja3Fingerprints) { + this.ja3Fingerprints = ja3Fingerprints; + } + + /** + * Getter for the JA4 fingerprints. + * @return a list of JA4 fingerprints. + */ + public List getJa4Fingerprints() { + return ja4Fingerprints; + } + + /** + * Setter for the JA4 fingerprints. + * @param ja4Fingerprints a list of JA4 fingerprints to set. + */ + public void setJa4Fingerprints(List ja4Fingerprints) { + this.ja4Fingerprints = ja4Fingerprints; + } + + /** + * Getter for the user agents. + * @return a list of user agents. + */ + public List getUserAgents() { + return userAgents; + } + + /** + * Setter for the user agents. + * @param userAgents a list of user agents to set. + */ + public void setUserAgents(List userAgents) { + this.userAgents = userAgents; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/networkacls/NetworkAcls.java b/src/main/java/com/auth0/json/mgmt/networkacls/NetworkAcls.java new file mode 100644 index 000000000..3385fa343 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/networkacls/NetworkAcls.java @@ -0,0 +1,114 @@ +package com.auth0.json.mgmt.networkacls; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class NetworkAcls { + @JsonProperty("description") + private String description; + @JsonProperty("active") + private boolean active; + @JsonProperty("priority") + private int priority; + @JsonProperty("id") + private String id; + @JsonProperty("rule") + private Rule rule; + @JsonProperty("created_at") + private String createdAt; + @JsonProperty("updated_at") + private String updatedAt; + + /** + * Getter for the ID of the network ACL. + * @return the ID of the network ACL. + */ + public String getId() { + return id; + } + + /** + * Getter for the creation timestamp of the network ACL. + * @return the creation timestamp of the network ACL. + */ + public String getCreatedAt() { + return createdAt; + } + + /** + * Getter for the last updated timestamp of the network ACL. + * @return the last updated timestamp of the network ACL. + */ + public String getUpdatedAt() { + return updatedAt; + } + + /** + * Getter for the description of the network ACL. + * @return the description of the network ACL. + */ + public String getDescription() { + return description; + } + + /** + * Setter for the description of the network ACL. + * @param description the description to set for the network ACL. + */ + public void setDescription(String description) { + this.description = description; + } + + /** + * Checks if the network ACL is active. + * @return true if the network ACL is active, false otherwise. + */ + @JsonProperty("active") + public boolean isActive() { + return active; + } + + /** + * Setter for the active status of the network ACL. + * @param active true to set the network ACL as active, false to set it as inactive. + */ + @JsonProperty("active") + public void setActive(boolean active) { + this.active = active; + } + + /** + * Getter for the priority of the network ACL. + * @return the priority of the network ACL. + */ + public int getPriority() { + return priority; + } + + /** + * Setter for the priority of the network ACL. + * @param priority the priority to set for the network ACL. + */ + public void setPriority(int priority) { + this.priority = priority; + } + + /** + * Getter for the rule associated with the network ACL. + * @return the rule of the network ACL. + */ + public Rule getRule() { + return rule; + } + + /** + * Setter for the rule associated with the network ACL. + * @param rule the rule to set for the network ACL. + */ + public void setRule(Rule rule) { + this.rule = rule; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/networkacls/NetworkAclsPage.java b/src/main/java/com/auth0/json/mgmt/networkacls/NetworkAclsPage.java new file mode 100644 index 000000000..192b8ab40 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/networkacls/NetworkAclsPage.java @@ -0,0 +1,22 @@ +package com.auth0.json.mgmt.networkacls; + +import com.auth0.json.mgmt.Page; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; + +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonDeserialize(using = NetworkAclsPageDeserializer.class) +public class NetworkAclsPage extends Page { + + public NetworkAclsPage(List items) { + super(items); + } + + public NetworkAclsPage(Integer start, Integer length, Integer total, Integer limit, List items) { + super(start, length, total, limit, items); + } +} diff --git a/src/main/java/com/auth0/json/mgmt/networkacls/NetworkAclsPageDeserializer.java b/src/main/java/com/auth0/json/mgmt/networkacls/NetworkAclsPageDeserializer.java new file mode 100644 index 000000000..100fd5bde --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/networkacls/NetworkAclsPageDeserializer.java @@ -0,0 +1,21 @@ +package com.auth0.json.mgmt.networkacls; + +import com.auth0.json.mgmt.PageDeserializer; + +import java.util.List; + +public class NetworkAclsPageDeserializer extends PageDeserializer { + protected NetworkAclsPageDeserializer() { + super(NetworkAcls.class, "network_acls"); + } + + @Override + protected NetworkAclsPage createPage(List items) { + return new NetworkAclsPage(items); + } + + @Override + protected NetworkAclsPage createPage(Integer start, Integer length, Integer total, Integer limit, List items) { + return new NetworkAclsPage(start, length, total, limit, items); + } +} diff --git a/src/main/java/com/auth0/json/mgmt/networkacls/Rule.java b/src/main/java/com/auth0/json/mgmt/networkacls/Rule.java new file mode 100644 index 000000000..dad6bca7f --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/networkacls/Rule.java @@ -0,0 +1,84 @@ +package com.auth0.json.mgmt.networkacls; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class Rule { + @JsonProperty("action") + private Action action; + @JsonProperty("match") + private Match match; + @JsonProperty("not_match") + private Match notMatch; + @JsonProperty("scope") + private String scope; + + /** + * Getter for the action associated with the rule. + * @return the action. + */ + public Action getAction() { + return action; + } + + /** + * Setter for the action associated with the rule. + * @param action the action to set. + */ + public void setAction(Action action) { + this.action = action; + } + + /** + * Getter for the match criteria of the rule. + * @return the match criteria. + */ + public Match getMatch() { + return match; + } + + /** + * Setter for the match criteria of the rule. + * @param match the match criteria to set. + */ + public void setMatch(Match match) { + this.match = match; + } + + /** + * Getter for the not match criteria of the rule. + * @return the not match criteria. + */ + public Match getNotMatch() { + return notMatch; + } + + /** + * Setter for the not match criteria of the rule. + * @param notMatch the not match criteria to set. + */ + public void setNotMatch(Match notMatch) { + this.notMatch = notMatch; + } + + /** + * Getter for the scope of the rule. + * @return the scope of the rule. + */ + public String getScope() { + return scope; + } + + /** + * Setter for the scope of the rule. + * @param scope the scope to set for the rule. + */ + public void setScope(String scope) { + this.scope = scope; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/organizations/CreateOrganizationClientGrantRequestBody.java b/src/main/java/com/auth0/json/mgmt/organizations/CreateOrganizationClientGrantRequestBody.java new file mode 100644 index 000000000..451276db3 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/organizations/CreateOrganizationClientGrantRequestBody.java @@ -0,0 +1,28 @@ +package com.auth0.json.mgmt.organizations; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Represents the body of the request to send when associating a client grant with an organization. + * @see com.auth0.client.mgmt.OrganizationsEntity#addClientGrant(String, CreateOrganizationClientGrantRequestBody) + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class CreateOrganizationClientGrantRequestBody { + + @JsonProperty("grant_id") + private String grantId; + + /** + * Create a new instance. + * @param grantId the ID of the grant. + */ + @JsonCreator + public CreateOrganizationClientGrantRequestBody(String grantId) { + this.grantId = grantId; + } + +} diff --git a/src/main/java/com/auth0/json/mgmt/organizations/EnabledConnection.java b/src/main/java/com/auth0/json/mgmt/organizations/EnabledConnection.java index 1233e6077..0361ea608 100644 --- a/src/main/java/com/auth0/json/mgmt/organizations/EnabledConnection.java +++ b/src/main/java/com/auth0/json/mgmt/organizations/EnabledConnection.java @@ -18,6 +18,10 @@ public class EnabledConnection { private boolean assignMembershipOnLogin; @JsonProperty("connection_id") private String connectionId; + @JsonProperty("show_as_button") + private Boolean showAsButton; + @JsonProperty("is_signup_enabled") + private Boolean isSignupEnabled; public EnabledConnection() {} @@ -77,4 +81,37 @@ public String getConnectionId() { public void setConnectionId(String connectionId) { this.connectionId = connectionId; } + + /** + * @return the value of the {@code show_as_button} field. + */ + public Boolean getShowAsButton() { + return showAsButton; + } + + /** + * Sets the {@code show_as_button} value. + * + * @param showAsButton the value for {@code show_as_button}. + */ + public void setShowAsButton(Boolean showAsButton) { + this.showAsButton = showAsButton; + } + + /** + * @return whether signup is enabled for this connection. + */ + @JsonProperty("is_signup_enabled") + public Boolean getSignupEnabled() { + return isSignupEnabled; + } + + /** + * Sets whether signup is enabled for this connection. + * @param signupEnabled {@code true} to enable signup, {@code false} to disable it. + */ + @JsonProperty("is_signup_enabled") + public void setSignupEnabled(Boolean signupEnabled) { + isSignupEnabled = signupEnabled; + } } diff --git a/src/main/java/com/auth0/json/mgmt/organizations/Member.java b/src/main/java/com/auth0/json/mgmt/organizations/Member.java index 74a4fbbe4..5c1f073fa 100644 --- a/src/main/java/com/auth0/json/mgmt/organizations/Member.java +++ b/src/main/java/com/auth0/json/mgmt/organizations/Member.java @@ -1,9 +1,12 @@ package com.auth0.json.mgmt.organizations; +import com.auth0.json.mgmt.roles.Role; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; + /** * Represents the member of an organization. * @see com.auth0.client.mgmt.OrganizationsEntity @@ -20,6 +23,8 @@ public class Member { private String picture; @JsonProperty("name") private String name; + @JsonProperty("roles") + private List roles; /** * @return the user ID of this Member. @@ -75,4 +80,8 @@ public String getName() { public void setName(String name) { this.name = name; } + + public List getRoles() { + return roles; + } } diff --git a/src/main/java/com/auth0/json/mgmt/organizations/Organization.java b/src/main/java/com/auth0/json/mgmt/organizations/Organization.java index 0798720e3..1b7142492 100644 --- a/src/main/java/com/auth0/json/mgmt/organizations/Organization.java +++ b/src/main/java/com/auth0/json/mgmt/organizations/Organization.java @@ -1,5 +1,7 @@ package com.auth0.json.mgmt.organizations; +import com.auth0.client.mgmt.filter.PageFilter; +import com.auth0.json.mgmt.tokenquota.TokenQuota; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; @@ -28,6 +30,8 @@ public class Organization { private Branding branding; @JsonProperty("enabled_connections") private List enabledConnections; + @JsonProperty("token_quota") + private TokenQuota tokenQuota; public Organization() {} @@ -114,7 +118,11 @@ public void setMetadata(Map metadata) { /** * @return the enabled connections of this Organization. + * @deprecated the {@code enabled_connections} property was removed from the API response body, so this will always + * return {@code null}. Use {@link com.auth0.client.mgmt.OrganizationsEntity#getConnections(String, PageFilter)} + * instead. */ + @Deprecated public List getEnabledConnections() { return enabledConnections; } @@ -127,4 +135,20 @@ public List getEnabledConnections() { public void setEnabledConnections(List enabledConnections) { this.enabledConnections = enabledConnections; } + + /** + * @return the token quota of this Organization. + */ + public TokenQuota getTokenQuota() { + return tokenQuota; + } + + /** + * Sets the token quota of this Organization. + * + * @param tokenQuota the token quota of this Organization. + */ + public void setTokenQuota(TokenQuota tokenQuota) { + this.tokenQuota = tokenQuota; + } } diff --git a/src/main/java/com/auth0/json/mgmt/ClientGrant.java b/src/main/java/com/auth0/json/mgmt/organizations/OrganizationClientGrant.java similarity index 90% rename from src/main/java/com/auth0/json/mgmt/ClientGrant.java rename to src/main/java/com/auth0/json/mgmt/organizations/OrganizationClientGrant.java index 9551b334c..358fd3792 100644 --- a/src/main/java/com/auth0/json/mgmt/ClientGrant.java +++ b/src/main/java/com/auth0/json/mgmt/organizations/OrganizationClientGrant.java @@ -1,4 +1,4 @@ -package com.auth0.json.mgmt; +package com.auth0.json.mgmt.organizations; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; @@ -7,13 +7,12 @@ import java.util.List; /** - * Class that represents an Auth0 Client Grant object. Related to the {@link com.auth0.client.mgmt.ClientGrantsEntity} entity. + * Represents a client grant associated with an organization. + * @see com.auth0.client.mgmt.OrganizationsEntity */ -@SuppressWarnings("unused") @JsonIgnoreProperties(ignoreUnknown = true) @JsonInclude(JsonInclude.Include.NON_NULL) -public class ClientGrant { - +public class OrganizationClientGrant { @JsonProperty("id") private String id; @JsonProperty("client_id") @@ -92,4 +91,5 @@ public List getScope() { public void setScope(List scope) { this.scope = scope; } + } diff --git a/src/main/java/com/auth0/json/mgmt/organizations/OrganizationClientGrantsPage.java b/src/main/java/com/auth0/json/mgmt/organizations/OrganizationClientGrantsPage.java new file mode 100644 index 000000000..faa2961c7 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/organizations/OrganizationClientGrantsPage.java @@ -0,0 +1,27 @@ +package com.auth0.json.mgmt.organizations; + +import com.auth0.json.mgmt.Page; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; + +import java.util.List; + +/** + * Represents a page of a response when getting the client grants associated with an organization. + * @see OrganizationClientGrant + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonDeserialize(using = OrganizationClientGrantsPageDeserializer.class) +public class OrganizationClientGrantsPage extends Page { + + public OrganizationClientGrantsPage(List items) { + super(items); + } + + public OrganizationClientGrantsPage(Integer start, Integer length, Integer total, Integer limit, List items) { + super(start, length, total, limit, items); + } + +} diff --git a/src/main/java/com/auth0/json/mgmt/organizations/OrganizationClientGrantsPageDeserializer.java b/src/main/java/com/auth0/json/mgmt/organizations/OrganizationClientGrantsPageDeserializer.java new file mode 100644 index 000000000..c334e7599 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/organizations/OrganizationClientGrantsPageDeserializer.java @@ -0,0 +1,25 @@ +package com.auth0.json.mgmt.organizations; + +import com.auth0.json.mgmt.PageDeserializer; + +import java.util.List; + +/** + * Parses a paged response into its {@linkplain OrganizationClientGrant} representation. + */ +public class OrganizationClientGrantsPageDeserializer extends PageDeserializer { + + OrganizationClientGrantsPageDeserializer() { + super(OrganizationClientGrant.class, "client_grants"); + } + + @Override + protected OrganizationClientGrantsPage createPage(List items) { + return new OrganizationClientGrantsPage(items); + } + + @Override + protected OrganizationClientGrantsPage createPage(Integer start, Integer length, Integer total, Integer limit, List items) { + return new OrganizationClientGrantsPage(start, length, total, limit, items); + } +} diff --git a/src/main/java/com/auth0/json/mgmt/Permission.java b/src/main/java/com/auth0/json/mgmt/permissions/Permission.java similarity index 98% rename from src/main/java/com/auth0/json/mgmt/Permission.java rename to src/main/java/com/auth0/json/mgmt/permissions/Permission.java index 09cf81ea9..537076b86 100644 --- a/src/main/java/com/auth0/json/mgmt/Permission.java +++ b/src/main/java/com/auth0/json/mgmt/permissions/Permission.java @@ -1,4 +1,4 @@ -package com.auth0.json.mgmt; +package com.auth0.json.mgmt.permissions; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; diff --git a/src/main/java/com/auth0/json/mgmt/PermissionSource.java b/src/main/java/com/auth0/json/mgmt/permissions/PermissionSource.java similarity index 96% rename from src/main/java/com/auth0/json/mgmt/PermissionSource.java rename to src/main/java/com/auth0/json/mgmt/permissions/PermissionSource.java index 7b1528daa..a3a6b4f52 100644 --- a/src/main/java/com/auth0/json/mgmt/PermissionSource.java +++ b/src/main/java/com/auth0/json/mgmt/permissions/PermissionSource.java @@ -1,4 +1,4 @@ -package com.auth0.json.mgmt; +package com.auth0.json.mgmt.permissions; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; diff --git a/src/main/java/com/auth0/json/mgmt/PermissionsPage.java b/src/main/java/com/auth0/json/mgmt/permissions/PermissionsPage.java similarity index 90% rename from src/main/java/com/auth0/json/mgmt/PermissionsPage.java rename to src/main/java/com/auth0/json/mgmt/permissions/PermissionsPage.java index b3786e060..f13ac1026 100644 --- a/src/main/java/com/auth0/json/mgmt/PermissionsPage.java +++ b/src/main/java/com/auth0/json/mgmt/permissions/PermissionsPage.java @@ -1,5 +1,6 @@ -package com.auth0.json.mgmt; +package com.auth0.json.mgmt.permissions; +import com.auth0.json.mgmt.Page; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; diff --git a/src/main/java/com/auth0/json/mgmt/PermissionsPageDeserializer.java b/src/main/java/com/auth0/json/mgmt/permissions/PermissionsPageDeserializer.java similarity index 90% rename from src/main/java/com/auth0/json/mgmt/PermissionsPageDeserializer.java rename to src/main/java/com/auth0/json/mgmt/permissions/PermissionsPageDeserializer.java index e6599089b..74d71ffad 100644 --- a/src/main/java/com/auth0/json/mgmt/PermissionsPageDeserializer.java +++ b/src/main/java/com/auth0/json/mgmt/permissions/PermissionsPageDeserializer.java @@ -1,4 +1,6 @@ -package com.auth0.json.mgmt; +package com.auth0.json.mgmt.permissions; + +import com.auth0.json.mgmt.PageDeserializer; import java.util.List; diff --git a/src/main/java/com/auth0/json/mgmt/prompts/Prompt.java b/src/main/java/com/auth0/json/mgmt/prompts/Prompt.java new file mode 100644 index 000000000..b7e1ca3a2 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/prompts/Prompt.java @@ -0,0 +1,64 @@ +package com.auth0.json.mgmt.prompts; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class Prompt { + @JsonProperty("universal_login_experience") + private String universalLoginExperience; + @JsonProperty("identifier_first") + private boolean identifierFirst; + @JsonProperty("webauthn_platform_first_factor") + private boolean webauthnPlatformFirstFactor; + + /** + * Getter for the universal login experience. + * @return the universal login experience. + */ + public String getUniversalLoginExperience() { + return universalLoginExperience; + } + + /** + * Setter for the universal login experience. + * @param universalLoginExperience the universal login experience to set. + */ + public void setUniversalLoginExperience(String universalLoginExperience) { + this.universalLoginExperience = universalLoginExperience; + } + + /** + * Getter for the identifier first. + * @return the identifier first. + */ + public boolean isIdentifierFirst() { + return identifierFirst; + } + + /** + * Setter for the identifier first. + * @param identifierFirst the identifier first to set. + */ + public void setIdentifierFirst(boolean identifierFirst) { + this.identifierFirst = identifierFirst; + } + + /** + * Getter for the webauthn platform first factor. + * @return the webauthn platform first factor. + */ + public boolean isWebauthnPlatformFirstFactor() { + return webauthnPlatformFirstFactor; + } + + /** + * Setter for the webauthn platform first factor. + * @param webauthnPlatformFirstFactor the webauthn platform first factor to set. + */ + public void setWebauthnPlatformFirstFactor(boolean webauthnPlatformFirstFactor) { + this.webauthnPlatformFirstFactor = webauthnPlatformFirstFactor; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/refreshtokens/Device.java b/src/main/java/com/auth0/json/mgmt/refreshtokens/Device.java new file mode 100644 index 000000000..e83e61339 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/refreshtokens/Device.java @@ -0,0 +1,64 @@ +package com.auth0.json.mgmt.refreshtokens; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class Device { + @JsonProperty("initial_ip") + private String initialIp; + @JsonProperty("initial_asn") + private String initialAsn; + @JsonProperty("initial_user_agent") + private String initialUserAgent; + @JsonProperty("last_ip") + private String lastIp; + @JsonProperty("last_asn") + private String lastAsn; + @JsonProperty("last_user_agent") + private String lastUserAgent; + + /** + * @return First IP address associated with this session + */ + public String getInitialIp() { + return initialIp; + } + + /** + * @return First autonomous system number associated with this session + */ + public String getInitialAsn() { + return initialAsn; + } + + /** + * @return First user agent associated with this session + */ + public String getInitialUserAgent() { + return initialUserAgent; + } + + /** + * @return Last IP address from which this user logged in + */ + public String getLastIp() { + return lastIp; + } + + /** + * @return Last autonomous system number from which this user logged in + */ + public String getLastAsn() { + return lastAsn; + } + + /** + * @return Last user agent of the device from which this user logged in + */ + public String getLastUserAgent() { + return lastUserAgent; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/refreshtokens/RefreshToken.java b/src/main/java/com/auth0/json/mgmt/refreshtokens/RefreshToken.java new file mode 100644 index 000000000..2efc36b00 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/refreshtokens/RefreshToken.java @@ -0,0 +1,115 @@ +package com.auth0.json.mgmt.refreshtokens; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Date; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class RefreshToken { + @JsonProperty("id") + private String id; + @JsonProperty("user_id") + private String userId; + @JsonProperty("created_at") + private Date createdAt; + @JsonProperty("idle_expires_at") + private Date idleExpiresAt; + @JsonProperty("expires_at") + private Date expiresAt; + @JsonProperty("device") + private Device device; + @JsonProperty("client_id") + private String clientId; + @JsonProperty("session_id") + private String sessionId; + @JsonProperty("rotating") + private Boolean rotating; + @JsonProperty("resource_servers") + private List resourceServers; + @JsonProperty("last_exchanged_at") + private Date lastExchangedAt; + + /** + * @return The ID of the refresh token + */ + public String getId() { + return id; + } + + /** + * @return ID of the user which can be used when interacting with other APIs. + */ + public String getUserId() { + return userId; + } + + /** + * @return The date and time when the refresh token was created + */ + public Date getCreatedAt() { + return createdAt; + } + + /** + * + * @return The date and time when the refresh token will expire if idle + */ + public Date getIdleExpiresAt() { + return idleExpiresAt; + } + + /** + * + * @return The date and time when the refresh token will expire + */ + public Date getExpiresAt() { + return expiresAt; + } + + /** + * @return Device information + */ + public Device getDevice() { + return device; + } + + /** + * @return ID of the client application granted with this refresh token + */ + public String getClientId() { + return clientId; + } + + /** + * + * @return ID of the authenticated session used to obtain this refresh-token + */ + public String getSessionId() { + return sessionId; + } + + /** + * @return True if the token is a rotating refresh token + */ + public Boolean isRotating() { + return rotating; + } + + /** + * @return A list of the resource server IDs associated to this refresh-token and their granted scopes + */ + public List getResourceServers() { + return resourceServers; + } + + /** + * @return The date and time when the refresh token was last exchanged + */ + public Date getLastExchangedAt() { + return lastExchangedAt; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/refreshtokens/RefreshTokensPage.java b/src/main/java/com/auth0/json/mgmt/refreshtokens/RefreshTokensPage.java new file mode 100644 index 000000000..9aea796c3 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/refreshtokens/RefreshTokensPage.java @@ -0,0 +1,44 @@ +package com.auth0.json.mgmt.refreshtokens; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * Class that represents a page of Refresh Tokens. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class RefreshTokensPage { + @JsonProperty("total") + private Integer total; + + @JsonProperty("next") + private String next; + + @JsonProperty("tokens") + private List tokens; + + /** + * @return the total number of refresh tokens. This is only present when `include_totals` is passed as a query parameter. + */ + public Integer getTotal() { + return total; + } + + /** + * @return the token ID from which to start selection for a new page + */ + public String getNext() { + return next; + } + + /** + * @return the list of Tokens + */ + public List getTokens() { + return tokens; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/refreshtokens/ResourceServer.java b/src/main/java/com/auth0/json/mgmt/refreshtokens/ResourceServer.java new file mode 100644 index 000000000..2c0c4a9e6 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/refreshtokens/ResourceServer.java @@ -0,0 +1,30 @@ +package com.auth0.json.mgmt.refreshtokens; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ResourceServer { + @JsonProperty("audience") + private String audience; + @JsonProperty("scopes") + private String scopes; + + /** + * @return Resource server ID + */ + public String getAudience() { + return audience; + } + + /** + * @return List of scopes for the refresh token + */ + public String getScopes() { + return scopes; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/resourceserver/AuthorizationDetails.java b/src/main/java/com/auth0/json/mgmt/resourceserver/AuthorizationDetails.java new file mode 100644 index 000000000..69989507c --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/resourceserver/AuthorizationDetails.java @@ -0,0 +1,33 @@ +package com.auth0.json.mgmt.resourceserver; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Class that represents the authorization details associated with a {@link ResourceServer} + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class AuthorizationDetails { + + @JsonProperty("type") + private String type; + + /** + * Create a new instance. + * @param type the value of the {@code type} field. + */ + @JsonCreator + public AuthorizationDetails(@JsonProperty("type") String type) { + this.type = type; + } + + /** + * @return the value of the {@code type} field + */ + public String getType() { + return type; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/resourceserver/EncryptionKey.java b/src/main/java/com/auth0/json/mgmt/resourceserver/EncryptionKey.java new file mode 100644 index 000000000..74f19707f --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/resourceserver/EncryptionKey.java @@ -0,0 +1,99 @@ +package com.auth0.json.mgmt.resourceserver; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Class that represents the encryption key associated with a {@link TokenEncryption} + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class EncryptionKey { + + @JsonProperty("name") + private String name; + @JsonProperty("alg") + private String alg; + @JsonProperty("pem") + private String pem; + @JsonProperty("kid") + private String kid; + @JsonProperty("thumbprint_sha256") + private String thumbprintSha256; + + /** + * @return the value of the {@code name} field. + */ + public String getName() { + return name; + } + + /** + * Sets the value of the {@code name} field. + * @param name the value of the {@code name} field. + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return the value of the {@code alg} field. + */ + public String getAlg() { + return alg; + } + + /** + * Sets the value of the {@code alg} field. + * @param alg the value of the {@code alg} field. + */ + public void setAlg(String alg) { + this.alg = alg; + } + + /** + * @return the value of the {@code pem} field. + */ + public String getPem() { + return pem; + } + + /** + * Sets the value of the {@code pem} field. + * @param pem the value of the {@code pem} field. + */ + public void setPem(String pem) { + this.pem = pem; + } + + /** + * @return the value of the {@code kid} field. + */ + public String getKid() { + return kid; + } + + /** + * Sets the value of the {@code kid} field. + * @param kid the value of the {@code kid} field. + */ + public void setKid(String kid) { + this.kid = kid; + } + + /** + * @return the value of the {@code thumbprint_sha256} field. + */ + public String getThumbprintSha256() { + return thumbprintSha256; + } + + /** + * Sets the value of the {@code thumbprint_sha256} field. + * @param thumbprintSha256 the value of the {@code thumbprint_sha256} field. + */ + public void setThumbprintSha256(String thumbprintSha256) { + this.thumbprintSha256 = thumbprintSha256; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/resourceserver/ProofOfPossession.java b/src/main/java/com/auth0/json/mgmt/resourceserver/ProofOfPossession.java new file mode 100644 index 000000000..5c7be6eb4 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/resourceserver/ProofOfPossession.java @@ -0,0 +1,54 @@ +package com.auth0.json.mgmt.resourceserver; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ProofOfPossession { + + @JsonProperty("mechanism") + private String mechanism; + @JsonProperty("required") + private Boolean required; + + @JsonCreator + public ProofOfPossession(@JsonProperty("mechanism") String mechanism, @JsonProperty("required") Boolean required) { + this.mechanism = mechanism; + this.required = required; + } + + /** + * Getter for the mechanism of the Proof of Possession. + * @return the mechanism of the Proof of Possession. + */ + public String getMechanism() { + return mechanism; + } + + /** + * Setter for the mechanism of the Proof of Possession. + * @param mechanism the mechanism of the Proof of Possession. + */ + public void setMechanism(String mechanism) { + this.mechanism = mechanism; + } + + /** + * Getter for the required flag of the Proof of Possession. + * @return the required flag of the Proof of Possession. + */ + public Boolean getRequired() { + return required; + } + + /** + * Setter for the required flag of the Proof of Possession. + * @param required the required flag of the Proof of Possession. + */ + public void setRequired(Boolean required) { + this.required = required; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/ResourceServer.java b/src/main/java/com/auth0/json/mgmt/resourceserver/ResourceServer.java similarity index 69% rename from src/main/java/com/auth0/json/mgmt/ResourceServer.java rename to src/main/java/com/auth0/json/mgmt/resourceserver/ResourceServer.java index 91bfb092b..0c80f5c0b 100644 --- a/src/main/java/com/auth0/json/mgmt/ResourceServer.java +++ b/src/main/java/com/auth0/json/mgmt/resourceserver/ResourceServer.java @@ -1,4 +1,4 @@ -package com.auth0.json.mgmt; +package com.auth0.json.mgmt.resourceserver; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @@ -39,6 +39,14 @@ public class ResourceServer { private Boolean isSystem; @JsonProperty("enforce_policies") private Boolean enforcePolicies; + @JsonProperty("consent_policy") + private String consentPolicy; + @JsonProperty("authorization_details") + private List authorizationDetails; + @JsonProperty("token_encryption") + private TokenEncryption tokenEncryption; + @JsonProperty("proof_of_possession") + private ProofOfPossession proofOfPossession; @JsonCreator public ResourceServer(@JsonProperty("identifier") String identifier) { @@ -178,4 +186,63 @@ public void setTokenLifetimeForWeb(Integer tokenLifetimeForWeb) { this.tokenLifetimeForWeb = tokenLifetimeForWeb; } + /** + * @return the value of the {@code consent_policy} field. + */ + public String getConsentPolicy() { + return consentPolicy; + } + + /** + * Sets the value of the {@code consent_policy} field + * @param consentPolicy the value of the {@code consent_policy} field + */ + public void setConsentPolicy(String consentPolicy) { + this.consentPolicy = consentPolicy; + } + + /** + * @return the value of the {@code authorization_details} field. + */ + public List getAuthorizationDetails() { + return authorizationDetails; + } + + /** + * Sets the value of the {@code authorization_details} field. + * @param authorizationDetails the value of the {@code authorization_details} field. + */ + public void setAuthorizationDetails(List authorizationDetails) { + this.authorizationDetails = authorizationDetails; + } + + /** + * @return the value of the {@code token_encryption} field. + */ + public TokenEncryption getTokenEncryption() { + return tokenEncryption; + } + + /** + * Sets the value of the {@code token_encryption} field. + * @param tokenEncryption the value of the {@code token_encryption} field. + */ + public void setTokenEncryption(TokenEncryption tokenEncryption) { + this.tokenEncryption = tokenEncryption; + } + + /** + * @return the value of the {@code proof_of_possession} field. + */ + public ProofOfPossession getProofOfPossession() { + return proofOfPossession; + } + + /** + * Sets the value of the {@code proof_of_possession} field. + * @param proofOfPossession the value of the {@code proof_of_possession} field. + */ + public void setProofOfPossession(ProofOfPossession proofOfPossession) { + this.proofOfPossession = proofOfPossession; + } } diff --git a/src/main/java/com/auth0/json/mgmt/ResourceServersPage.java b/src/main/java/com/auth0/json/mgmt/resourceserver/ResourceServersPage.java similarity index 91% rename from src/main/java/com/auth0/json/mgmt/ResourceServersPage.java rename to src/main/java/com/auth0/json/mgmt/resourceserver/ResourceServersPage.java index 555d8969b..dc021659c 100644 --- a/src/main/java/com/auth0/json/mgmt/ResourceServersPage.java +++ b/src/main/java/com/auth0/json/mgmt/resourceserver/ResourceServersPage.java @@ -1,5 +1,6 @@ -package com.auth0.json.mgmt; +package com.auth0.json.mgmt.resourceserver; +import com.auth0.json.mgmt.Page; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; @@ -23,4 +24,4 @@ public ResourceServersPage(Integer start, Integer length, Integer total, Integer super(start, length, total, limit, items); } -} \ No newline at end of file +} diff --git a/src/main/java/com/auth0/json/mgmt/ResourceServersPageDeserializer.java b/src/main/java/com/auth0/json/mgmt/resourceserver/ResourceServersPageDeserializer.java similarity index 90% rename from src/main/java/com/auth0/json/mgmt/ResourceServersPageDeserializer.java rename to src/main/java/com/auth0/json/mgmt/resourceserver/ResourceServersPageDeserializer.java index 3deff4347..d85c7cd86 100644 --- a/src/main/java/com/auth0/json/mgmt/ResourceServersPageDeserializer.java +++ b/src/main/java/com/auth0/json/mgmt/resourceserver/ResourceServersPageDeserializer.java @@ -1,4 +1,6 @@ -package com.auth0.json.mgmt; +package com.auth0.json.mgmt.resourceserver; + +import com.auth0.json.mgmt.PageDeserializer; import java.util.List; diff --git a/src/main/java/com/auth0/json/mgmt/Scope.java b/src/main/java/com/auth0/json/mgmt/resourceserver/Scope.java similarity index 95% rename from src/main/java/com/auth0/json/mgmt/Scope.java rename to src/main/java/com/auth0/json/mgmt/resourceserver/Scope.java index 5dcba2d50..b7af7f6d8 100644 --- a/src/main/java/com/auth0/json/mgmt/Scope.java +++ b/src/main/java/com/auth0/json/mgmt/resourceserver/Scope.java @@ -1,4 +1,4 @@ -package com.auth0.json.mgmt; +package com.auth0.json.mgmt.resourceserver; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; diff --git a/src/main/java/com/auth0/json/mgmt/resourceserver/TokenEncryption.java b/src/main/java/com/auth0/json/mgmt/resourceserver/TokenEncryption.java new file mode 100644 index 000000000..86aa0f516 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/resourceserver/TokenEncryption.java @@ -0,0 +1,43 @@ +package com.auth0.json.mgmt.resourceserver; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Class that represents the token encryption associated with a {@link ResourceServer} + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class TokenEncryption { + + @JsonProperty("format") + private String format; + @JsonProperty("encryption_key") + private EncryptionKey encryptionKey; + + /** + * Create a new instance. + * @param format the value of the {@code format} field. + * @param encryptionKey the value of the {@code encryption_key} field. + */ + @JsonCreator + public TokenEncryption(@JsonProperty("format") String format, @JsonProperty("encryption_key") EncryptionKey encryptionKey) { + this.format = format; + this.encryptionKey = encryptionKey; + } + /** + * @return the value of the {@code format} field. + */ + public String getFormat() { + return format; + } + + /** + * @return the value of the {@code encryption_key} field. + */ + public EncryptionKey getEncryptionKey() { + return encryptionKey; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/Role.java b/src/main/java/com/auth0/json/mgmt/roles/Role.java similarity index 97% rename from src/main/java/com/auth0/json/mgmt/Role.java rename to src/main/java/com/auth0/json/mgmt/roles/Role.java index 0f095b6fa..c1f5068a4 100644 --- a/src/main/java/com/auth0/json/mgmt/Role.java +++ b/src/main/java/com/auth0/json/mgmt/roles/Role.java @@ -1,4 +1,4 @@ -package com.auth0.json.mgmt; +package com.auth0.json.mgmt.roles; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; diff --git a/src/main/java/com/auth0/json/mgmt/RolesPage.java b/src/main/java/com/auth0/json/mgmt/roles/RolesPage.java similarity index 90% rename from src/main/java/com/auth0/json/mgmt/RolesPage.java rename to src/main/java/com/auth0/json/mgmt/roles/RolesPage.java index 282afac56..61af9d66b 100644 --- a/src/main/java/com/auth0/json/mgmt/RolesPage.java +++ b/src/main/java/com/auth0/json/mgmt/roles/RolesPage.java @@ -1,5 +1,6 @@ -package com.auth0.json.mgmt; +package com.auth0.json.mgmt.roles; +import com.auth0.json.mgmt.Page; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; diff --git a/src/main/java/com/auth0/json/mgmt/RolesPageDeserializer.java b/src/main/java/com/auth0/json/mgmt/roles/RolesPageDeserializer.java similarity index 89% rename from src/main/java/com/auth0/json/mgmt/RolesPageDeserializer.java rename to src/main/java/com/auth0/json/mgmt/roles/RolesPageDeserializer.java index 40c4398ad..2df11828b 100644 --- a/src/main/java/com/auth0/json/mgmt/RolesPageDeserializer.java +++ b/src/main/java/com/auth0/json/mgmt/roles/RolesPageDeserializer.java @@ -1,4 +1,6 @@ -package com.auth0.json.mgmt; +package com.auth0.json.mgmt.roles; + +import com.auth0.json.mgmt.PageDeserializer; import java.util.List; diff --git a/src/main/java/com/auth0/json/mgmt/Rule.java b/src/main/java/com/auth0/json/mgmt/rules/Rule.java similarity index 98% rename from src/main/java/com/auth0/json/mgmt/Rule.java rename to src/main/java/com/auth0/json/mgmt/rules/Rule.java index 4dae475aa..be11eb401 100644 --- a/src/main/java/com/auth0/json/mgmt/Rule.java +++ b/src/main/java/com/auth0/json/mgmt/rules/Rule.java @@ -1,4 +1,4 @@ -package com.auth0.json.mgmt; +package com.auth0.json.mgmt.rules; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; diff --git a/src/main/java/com/auth0/json/mgmt/RulesConfig.java b/src/main/java/com/auth0/json/mgmt/rules/RulesConfig.java similarity index 97% rename from src/main/java/com/auth0/json/mgmt/RulesConfig.java rename to src/main/java/com/auth0/json/mgmt/rules/RulesConfig.java index ec48c4188..1adf9aa7d 100644 --- a/src/main/java/com/auth0/json/mgmt/RulesConfig.java +++ b/src/main/java/com/auth0/json/mgmt/rules/RulesConfig.java @@ -1,4 +1,4 @@ -package com.auth0.json.mgmt; +package com.auth0.json.mgmt.rules; import com.auth0.client.mgmt.RulesConfigsEntity; import com.fasterxml.jackson.annotation.JsonCreator; diff --git a/src/main/java/com/auth0/json/mgmt/RulesPage.java b/src/main/java/com/auth0/json/mgmt/rules/RulesPage.java similarity index 91% rename from src/main/java/com/auth0/json/mgmt/RulesPage.java rename to src/main/java/com/auth0/json/mgmt/rules/RulesPage.java index 72dce1bc3..6da4e6618 100644 --- a/src/main/java/com/auth0/json/mgmt/RulesPage.java +++ b/src/main/java/com/auth0/json/mgmt/rules/RulesPage.java @@ -1,5 +1,6 @@ -package com.auth0.json.mgmt; +package com.auth0.json.mgmt.rules; +import com.auth0.json.mgmt.Page; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; @@ -23,4 +24,4 @@ public RulesPage(Integer start, Integer length, Integer total, Integer limit, Li super(start, length, total, limit, items); } -} \ No newline at end of file +} diff --git a/src/main/java/com/auth0/json/mgmt/RulesPageDeserializer.java b/src/main/java/com/auth0/json/mgmt/rules/RulesPageDeserializer.java similarity index 89% rename from src/main/java/com/auth0/json/mgmt/RulesPageDeserializer.java rename to src/main/java/com/auth0/json/mgmt/rules/RulesPageDeserializer.java index 5f3d27ff3..f163355e7 100644 --- a/src/main/java/com/auth0/json/mgmt/RulesPageDeserializer.java +++ b/src/main/java/com/auth0/json/mgmt/rules/RulesPageDeserializer.java @@ -1,4 +1,6 @@ -package com.auth0.json.mgmt; +package com.auth0.json.mgmt.rules; + +import com.auth0.json.mgmt.PageDeserializer; import java.util.List; diff --git a/src/main/java/com/auth0/json/mgmt/selfserviceprofiles/Branding.java b/src/main/java/com/auth0/json/mgmt/selfserviceprofiles/Branding.java new file mode 100644 index 000000000..55433ba72 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/selfserviceprofiles/Branding.java @@ -0,0 +1,46 @@ +package com.auth0.json.mgmt.selfserviceprofiles; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +public class Branding { + @JsonProperty("logo_url") + private String logoUrl; + @JsonProperty("colors") + private Color colors; + + /** + * Getter for the logo URL. + * @return the logo URL. + */ + public String getLogoUrl() { + return logoUrl; + } + + /** + * Setter for the logo URL. + * @param logoUrl the logo URL to set. + */ + public void setLogoUrl(String logoUrl) { + this.logoUrl = logoUrl; + } + + /** + * Getter for the colors. + * @return the colors. + */ + public Color getColors() { + return colors; + } + + /** + * Setter for the colors. + * @param colors the colors to set. + */ + public void setColors(Color colors) { + this.colors = colors; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/selfserviceprofiles/Color.java b/src/main/java/com/auth0/json/mgmt/selfserviceprofiles/Color.java new file mode 100644 index 000000000..87891fbab --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/selfserviceprofiles/Color.java @@ -0,0 +1,43 @@ +package com.auth0.json.mgmt.selfserviceprofiles; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +public class Color { + @JsonProperty("primary") + private String primary; + + /** + * Creates a new instance of the Color class. + */ + public Color() {} + + /** + * Creates a new instance of the Color class. + * @param primary the primary color. + */ + @JsonCreator + public Color(@JsonProperty("primary") String primary) { + this.primary = primary; + } + + /** + * Getter for the primary color. + * @return the primary color. + */ + public String getPrimary() { + return primary; + } + + /** + * Setter for the primary color. + * @param primary the primary color to set. + */ + public void setPrimary(String primary) { + this.primary = primary; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/selfserviceprofiles/DomainAliasesConfig.java b/src/main/java/com/auth0/json/mgmt/selfserviceprofiles/DomainAliasesConfig.java new file mode 100644 index 000000000..2502578b3 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/selfserviceprofiles/DomainAliasesConfig.java @@ -0,0 +1,29 @@ +package com.auth0.json.mgmt.selfserviceprofiles; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +public class DomainAliasesConfig { + @JsonProperty("domain_verification") + private String domainVerification; + + /** + * Creates a new instance of the DomainAliasesConfig class. + */ + @JsonCreator + public DomainAliasesConfig(@JsonProperty("domain_verification") String domainVerification) { + this.domainVerification = domainVerification; + } + + /** + * Getter for the domain verification. + * @return the domain verification. + */ + public String getDomainVerification() { + return domainVerification; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/selfserviceprofiles/EnabledOrganizations.java b/src/main/java/com/auth0/json/mgmt/selfserviceprofiles/EnabledOrganizations.java new file mode 100644 index 000000000..fada60683 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/selfserviceprofiles/EnabledOrganizations.java @@ -0,0 +1,64 @@ +package com.auth0.json.mgmt.selfserviceprofiles; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +public class EnabledOrganizations { + @JsonProperty("organization_id") + private String organizationId; + @JsonProperty("assign_membership_on_login") + private boolean assignMembershipOnLogin; + @JsonProperty("show_as_button") + private boolean showAsButton; + + /** + * Getter for the organization id. + * @return the organization id. + */ + public String getOrganizationId() { + return organizationId; + } + + /** + * Setter for the organization id. + * @param organizationId the organization id to set. + */ + public void setOrganizationId(String organizationId) { + this.organizationId = organizationId; + } + + /** + * Getter for the assign membership on login. + * @return the assign membership on login. + */ + public boolean isAssignMembershipOnLogin() { + return assignMembershipOnLogin; + } + + /** + * Setter for the assign membership on login. + * @param assignMembershipOnLogin the assign membership on login to set. + */ + public void setAssignMembershipOnLogin(boolean assignMembershipOnLogin) { + this.assignMembershipOnLogin = assignMembershipOnLogin; + } + + /** + * Getter for the show as button. + * @return the show as button. + */ + public boolean isShowAsButton() { + return showAsButton; + } + + /** + * Setter for the show as button. + * @param showAsButton the show as button to set. + */ + public void setShowAsButton(boolean showAsButton) { + this.showAsButton = showAsButton; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/selfserviceprofiles/GoogleWorkspaceProvisioningConfig.java b/src/main/java/com/auth0/json/mgmt/selfserviceprofiles/GoogleWorkspaceProvisioningConfig.java new file mode 100644 index 000000000..a20726c78 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/selfserviceprofiles/GoogleWorkspaceProvisioningConfig.java @@ -0,0 +1,22 @@ +package com.auth0.json.mgmt.selfserviceprofiles; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +public class GoogleWorkspaceProvisioningConfig { + @JsonProperty("sync_users") + private boolean syncUsers; + + @JsonProperty("sync_users") + public boolean isSyncUsers() { + return syncUsers; + } + + @JsonProperty("sync_users") + public void setSyncUsers(boolean syncUsers) { + this.syncUsers = syncUsers; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/selfserviceprofiles/ProvisioningConfig.java b/src/main/java/com/auth0/json/mgmt/selfserviceprofiles/ProvisioningConfig.java new file mode 100644 index 000000000..c39753d28 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/selfserviceprofiles/ProvisioningConfig.java @@ -0,0 +1,73 @@ +package com.auth0.json.mgmt.selfserviceprofiles; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +public class ProvisioningConfig { + @JsonProperty("scopes") + private List scopes; + @JsonProperty("token_lifetime") + private Integer tokenLifetime; + @JsonProperty("google_workspace") + private GoogleWorkspaceProvisioningConfig googleWorkspace; + + + /** + * Getter for the scopes. + * @return the scopes. + */ + @JsonProperty("scopes") + public List getScopes() { + return scopes; + } + + /** + * Setter for the scopes. + * @param scopes the scopes to set. + */ + @JsonProperty("scopes") + public void setScopes(List scopes) { + this.scopes = scopes; + } + + /** + * Getter for the Google Workspace provisioning config. + * @return the Google Workspace provisioning config. + */ + @JsonProperty("google_workspace") + public GoogleWorkspaceProvisioningConfig getGoogleWorkspace() { + return googleWorkspace; + } + + /** + * Getter for the token lifetime. + * @return the token lifetime. + */ + @JsonProperty("token_lifetime") + public Integer getTokenLifetime() { + return tokenLifetime; + } + + /** + * Setter for the token lifetime. + * @param tokenLifetime the token lifetime to set. + */ + @JsonProperty("token_lifetime") + public void setTokenLifetime(Integer tokenLifetime) { + this.tokenLifetime = tokenLifetime; + } + + /** + * Setter for the Google Workspace provisioning config. + * @param googleWorkspace the Google Workspace provisioning config to set. + */ + @JsonProperty("google_workspace") + public void setGoogleWorkspace(GoogleWorkspaceProvisioningConfig googleWorkspace) { + this.googleWorkspace = googleWorkspace; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/selfserviceprofiles/SelfServiceProfile.java b/src/main/java/com/auth0/json/mgmt/selfserviceprofiles/SelfServiceProfile.java new file mode 100644 index 000000000..534f0e074 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/selfserviceprofiles/SelfServiceProfile.java @@ -0,0 +1,121 @@ +package com.auth0.json.mgmt.selfserviceprofiles; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +public class SelfServiceProfile { + @JsonProperty("name") + private String name; + @JsonProperty("description") + private String description; + @JsonProperty("user_attributes") + private List userAttributes; + @JsonProperty("branding") + private Branding branding; + @JsonProperty("allowed_strategies") + private List allowedStrategies; + @JsonProperty("user_attribute_profile_id") + private String userAttributeProfileId; + + /** + * Getter for the name of the self-service profile. + * @return the name of the self-service profile. + */ + public String getName() { + return name; + } + + /** + * Setter for the name of the self-service profile. + * @param name the name of the self-service profile to set. + */ + public void setName(String name) { + this.name = name; + } + + /** + * Getter for the description of the self-service profile. + * @return the description of the self-service profile. + */ + public String getDescription() { + return description; + } + + /** + * Setter for the description of the self-service profile. + * @param description the description of the self-service profile to set. + */ + public void setDescription(String description) { + this.description = description; + } + + /** + * Getter for the user attributes of the self-service profile. + * @return the user attributes of the self-service profile. + */ + public List getUserAttributes() { + return userAttributes; + } + + /** + * Setter for the user attributes of the self-service profile. + * @param userAttributes the user attributes of the self-service profile to set. + */ + public void setUserAttributes(List userAttributes) { + this.userAttributes = userAttributes; + } + + /** + * Getter for the branding of the self-service profile. + * @return the branding of the self-service profile. + */ + public Branding getBranding() { + return branding; + } + + /** + * Setter for the branding of the self-service profile. + * @param branding the branding of the self-service profile to set. + */ + public void setBranding(Branding branding) { + this.branding = branding; + } + + /** + * Getter for the allowed strategies of the self-service profile. + * @return the allowed strategies of the self-service profile. + */ + public List getAllowedStrategies() { + return allowedStrategies; + } + + /** + * Setter for the allowed strategies of the self-service profile. + * @param allowedStrategies the allowed strategies of the self-service profile to set. + */ + public void setAllowedStrategies(List allowedStrategies) { + this.allowedStrategies = allowedStrategies; + } + + /** + * Getter for user attribute profile ID. + * @return the user attribute profile ID. + */ + public String getUserAttributeProfileId() { + return userAttributeProfileId; + } + + /** + * Setter for user attribute profile ID. + * @param userAttributeProfileId the user attribute profile ID to set. + */ + public void setUserAttributeProfileId(String userAttributeProfileId) { + this.userAttributeProfileId = userAttributeProfileId; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/selfserviceprofiles/SelfServiceProfileResponse.java b/src/main/java/com/auth0/json/mgmt/selfserviceprofiles/SelfServiceProfileResponse.java new file mode 100644 index 000000000..838bb9daf --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/selfserviceprofiles/SelfServiceProfileResponse.java @@ -0,0 +1,64 @@ +package com.auth0.json.mgmt.selfserviceprofiles; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class SelfServiceProfileResponse extends SelfServiceProfile { + @JsonProperty("id") + private String id; + @JsonProperty("created_at") + private String createdAt; + @JsonProperty("updated_at") + private String updatedAt; + + /** + * Getter for the id of the self-service profile. + * @return the id of the self-service profile. + */ + public String getId() { + return id; + } + + /** + * Setter for the id of the self-service profile. + * @param id the id of the self-service profile to set. + */ + public void setId(String id) { + this.id = id; + } + + /** + * Getter for the created at of the self-service profile. + * @return the created at of the self-service profile. + */ + public String getCreatedAt() { + return createdAt; + } + + /** + * Setter for the created at of the self-service profile. + * @param createdAt the created at of the self-service profile to set. + */ + public void setCreatedAt(String createdAt) { + this.createdAt = createdAt; + } + + /** + * Getter for the updated at of the self-service profile. + * @return the updated at of the self-service profile. + */ + public String getUpdatedAt() { + return updatedAt; + } + + /** + * Setter for the updated at of the self-service profile. + * @param updatedAt the updated at of the self-service profile to set. + */ + public void setUpdatedAt(String updatedAt) { + this.updatedAt = updatedAt; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/selfserviceprofiles/SelfServiceProfileResponsePage.java b/src/main/java/com/auth0/json/mgmt/selfserviceprofiles/SelfServiceProfileResponsePage.java new file mode 100644 index 000000000..e28d4cf74 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/selfserviceprofiles/SelfServiceProfileResponsePage.java @@ -0,0 +1,21 @@ +package com.auth0.json.mgmt.selfserviceprofiles; + +import com.auth0.json.mgmt.Page; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; + +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonDeserialize(using = SelfServiceProfileResponsePageDeserializer.class) +public class SelfServiceProfileResponsePage extends Page { + public SelfServiceProfileResponsePage(List items) { + super(items); + } + + public SelfServiceProfileResponsePage(Integer start, Integer length, Integer total, Integer limit, List items) { + super(start, length, total, limit, items); + } +} diff --git a/src/main/java/com/auth0/json/mgmt/selfserviceprofiles/SelfServiceProfileResponsePageDeserializer.java b/src/main/java/com/auth0/json/mgmt/selfserviceprofiles/SelfServiceProfileResponsePageDeserializer.java new file mode 100644 index 000000000..bebdbade6 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/selfserviceprofiles/SelfServiceProfileResponsePageDeserializer.java @@ -0,0 +1,23 @@ +package com.auth0.json.mgmt.selfserviceprofiles; + +import com.auth0.json.mgmt.PageDeserializer; + +import java.util.List; + + +public class SelfServiceProfileResponsePageDeserializer extends PageDeserializer { + + protected SelfServiceProfileResponsePageDeserializer() { + super(SelfServiceProfileResponse.class, "self_service_profiles"); + } + + @Override + protected SelfServiceProfileResponsePage createPage(List items) { + return new SelfServiceProfileResponsePage(items); + } + + @Override + protected SelfServiceProfileResponsePage createPage(Integer start, Integer length, Integer total, Integer limit, List items) { + return new SelfServiceProfileResponsePage(start, length, total, limit, items); + } +} diff --git a/src/main/java/com/auth0/json/mgmt/selfserviceprofiles/SsoAccessTicketRequest.java b/src/main/java/com/auth0/json/mgmt/selfserviceprofiles/SsoAccessTicketRequest.java new file mode 100644 index 000000000..7b9436664 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/selfserviceprofiles/SsoAccessTicketRequest.java @@ -0,0 +1,139 @@ +package com.auth0.json.mgmt.selfserviceprofiles; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; +import java.util.Map; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +public class SsoAccessTicketRequest { + @JsonProperty("connection_id") + private String connectionId; + @JsonProperty("connection_config") + private Map connectionConfig; + @JsonProperty("enabled_clients") + private List enabledClients; + @JsonProperty("enabled_organizations") + private List enabledOrganizations; + @JsonProperty("ttl_sec") + private int ttlSec; + @JsonProperty("domain_aliases_config") + private DomainAliasesConfig domainAliasesConfig; + @JsonProperty("provisioning_config") + private ProvisioningConfig provisioningConfig; + + /** + * Creates a new instance. + * @return the new instance. + */ + public String getConnectionId() { + return connectionId; + } + + /** + * Sets the connection ID. + * @param connectionId the connection ID to set. + */ + public void setConnectionId(String connectionId) { + this.connectionId = connectionId; + } + + /** + * Getter for the connection configuration. + * @return the connection configuration. + */ + public Map getConnectionConfig() { + return connectionConfig; + } + + /** + * Setter for the connection configuration. + * @param connectionConfig the connection configuration to set. + */ + public void setConnectionConfig(Map connectionConfig) { + this.connectionConfig = connectionConfig; + } + + /** + * Getter for the enabled clients. + * @return the enabled clients. + */ + public List getEnabledClients() { + return enabledClients; + } + + /** + * Setter for the enabled clients. + * @param enabledClients the enabled clients to set. + */ + public void setEnabledClients(List enabledClients) { + this.enabledClients = enabledClients; + } + + /** + * Getter for the enabled organizations. + * @return the enabled organizations. + */ + public List getEnabledOrganizations() { + return enabledOrganizations; + } + + /** + * Setter for the enabled organizations. + * @param enabledOrganizations the enabled organizations to set. + */ + public void setEnabledOrganizations(List enabledOrganizations) { + this.enabledOrganizations = enabledOrganizations; + } + + /** + * Getter for the TTL in seconds. + * @return the TTL in seconds. + */ + public int getTtlSec() { + return ttlSec; + } + + /** + * Setter for the TTL in seconds. + * @param ttlSec the TTL in seconds to set. + */ + public void setTtlSec(int ttlSec) { + this.ttlSec = ttlSec; + } + + /** + * Getter for the domain aliases configuration. + * @return the domain aliases configuration. + */ + public DomainAliasesConfig getDomainAliasesConfig() { + return domainAliasesConfig; + } + + /** + * Setter for the domain aliases configuration. + * @param domainAliasesConfig the domain aliases configuration to set. + */ + public void setDomainAliasesConfig(DomainAliasesConfig domainAliasesConfig) { + this.domainAliasesConfig = domainAliasesConfig; + } + + /** + * Getter for the provisioning configuration. + * @return the provisioning configuration. + */ + public ProvisioningConfig getProvisioningConfig() { + return provisioningConfig; + } + + /** + * Setter for the provisioning configuration. + * @param provisioningConfig the provisioning configuration to set. + */ + public void setProvisioningConfig(ProvisioningConfig provisioningConfig) { + this.provisioningConfig = provisioningConfig; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/selfserviceprofiles/SsoAccessTicketResponse.java b/src/main/java/com/auth0/json/mgmt/selfserviceprofiles/SsoAccessTicketResponse.java new file mode 100644 index 000000000..ab4bf3441 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/selfserviceprofiles/SsoAccessTicketResponse.java @@ -0,0 +1,41 @@ +package com.auth0.json.mgmt.selfserviceprofiles; + +import com.fasterxml.jackson.annotation.*; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +public class SsoAccessTicketResponse { + @JsonProperty("ticket") + private String ticket; + + /** + * Creates a new instance. + */ + public SsoAccessTicketResponse() { + } + + /** + * Creates a new instance with the given ticket. + * @param ticket the ticket. + */ + @JsonCreator + public SsoAccessTicketResponse(@JsonProperty("ticket") String ticket) { + this.ticket = ticket; + } + + /** + * Getter for the ticket. + * @return the ticket. + */ + public String getTicket() { + return ticket; + } + + /** + * Setter for the ticket. + * @param ticket the ticket to set. + */ + public void setTicket(String ticket) { + this.ticket = ticket; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/selfserviceprofiles/UserAttribute.java b/src/main/java/com/auth0/json/mgmt/selfserviceprofiles/UserAttribute.java new file mode 100644 index 000000000..33db0ad6b --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/selfserviceprofiles/UserAttribute.java @@ -0,0 +1,83 @@ +package com.auth0.json.mgmt.selfserviceprofiles; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +public class UserAttribute { + @JsonProperty("name") + private String name; + @JsonProperty("description") + private String description; + @JsonProperty("is_optional") + private boolean isOptional; + + /** + * Creates a new instance of the UserAttribute class. + */ + public UserAttribute() { } + + /** + * Creates a new instance of the UserAttribute class. + * @param name the name of the user attribute. + * @param description the description of the user attribute. + * @param isOptional the isOptional of the user attribute. + */ + @JsonCreator + public UserAttribute(@JsonProperty("name") String name, @JsonProperty("description") String description, @JsonProperty("is_optional") boolean isOptional) { + this.name = name; + this.description = description; + this.isOptional = isOptional; + } + + /** + * Getter for the name of the user attribute. + * @return the name of the user attribute. + */ + public String getName() { + return name; + } + + /** + * Setter for the name of the user attribute. + * @param name the name of the user attribute to set. + */ + public void setName(String name) { + this.name = name; + } + + /** + * Getter for the description of the user attribute. + * @return the description of the user attribute. + */ + public String getDescription() { + return description; + } + + /** + * Setter for the description of the user attribute. + * @param description the description of the user attribute to set. + */ + public void setDescription(String description) { + this.description = description; + } + + /** + * Getter for the isOptional of the user attribute. + * @return the isOptional of the user attribute. + */ + public boolean getIsOptional() { + return isOptional; + } + + /** + * Setter for the isOptional of the user attribute. + * @param isOptional the isOptional of the user attribute to set. + */ + public void setIsOptional(boolean isOptional) { + this.isOptional = isOptional; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/sessions/Authentication.java b/src/main/java/com/auth0/json/mgmt/sessions/Authentication.java new file mode 100644 index 000000000..177c14699 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/sessions/Authentication.java @@ -0,0 +1,21 @@ +package com.auth0.json.mgmt.sessions; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class Authentication { + @JsonProperty("methods") + private List methods; + + /** + * @return Contains the authentication methods a user has completed during their session + */ + public List getMethods() { + return methods; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/sessions/AuthenticationMethod.java b/src/main/java/com/auth0/json/mgmt/sessions/AuthenticationMethod.java new file mode 100644 index 000000000..012a29d61 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/sessions/AuthenticationMethod.java @@ -0,0 +1,39 @@ +package com.auth0.json.mgmt.sessions; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Date; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class AuthenticationMethod { + @JsonProperty("name") + private String name; + @JsonProperty("timestamp") + private Date timestamp; + @JsonProperty("type") + private String type; + + /** + * @return One of: "federated", "passkey", "pwd", "sms", "email", "mfa", "mock" or a custom method denoted by a URL + */ + public String getName() { + return name; + } + + /** + * @return Timestamp of when the signal was received + */ + public Date getTimestamp() { + return timestamp; + } + + /** + * @return A specific MFA factor. Only present when "name" is set to "mfa" + */ + public String getType() { + return type; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/sessions/Client.java b/src/main/java/com/auth0/json/mgmt/sessions/Client.java new file mode 100644 index 000000000..7ac383e65 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/sessions/Client.java @@ -0,0 +1,19 @@ +package com.auth0.json.mgmt.sessions; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class Client { + @JsonProperty("client_id") + private String clientId; + + /** + * @return ID of client for the session + */ + public String getClientId() { + return clientId; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/sessions/Device.java b/src/main/java/com/auth0/json/mgmt/sessions/Device.java new file mode 100644 index 000000000..cf3fe3954 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/sessions/Device.java @@ -0,0 +1,64 @@ +package com.auth0.json.mgmt.sessions; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class Device { + @JsonProperty("initial_user_agent") + private String initialUserAgent; + @JsonProperty("initial_ip") + private String initialIP; + @JsonProperty("initial_asn") + private String initialASN; + @JsonProperty("last_user_agent") + private String lastUserAgent; + @JsonProperty("last_ip") + private String lastIP; + @JsonProperty("last_asn") + private String lastASN; + + /** + * @return First user agent associated with this session + */ + public String getInitialUserAgent() { + return initialUserAgent; + } + + /** + * @return First IP address associated with this session + */ + public String getInitialIP() { + return initialIP; + } + + /** + * @return First autonomous system number associated with this session + */ + public String getInitialASN() { + return initialASN; + } + + /** + * @return Last user agent of the device from which this user logged in + */ + public String getLastUserAgent() { + return lastUserAgent; + } + + /** + * @return Last IP address from which this user logged in + */ + public String getLastIP() { + return lastIP; + } + + /** + * @return Last autonomous system number from which this user logged in + */ + public String getLastASN() { + return lastASN; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/sessions/Session.java b/src/main/java/com/auth0/json/mgmt/sessions/Session.java new file mode 100644 index 000000000..c231770e7 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/sessions/Session.java @@ -0,0 +1,106 @@ +package com.auth0.json.mgmt.sessions; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Date; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class Session { + @JsonProperty("id") + private String id; + @JsonProperty("user_id") + private String userId; + @JsonProperty("created_at") + private Date createdAt; + @JsonProperty("updated_at") + private Date updatedAt; + @JsonProperty("authenticated_at") + private Date authenticatedAt; + @JsonProperty("idle_expires_at") + private Date idleExpiresAt; + @JsonProperty("expires_at") + private Date expiresAt; + @JsonProperty("last_interacted_at") + private Date lastInteractedAt; + @JsonProperty("device") + private Device device; + @JsonProperty("clients") + private List clients; + @JsonProperty("authentication") + private Authentication authentication; + + /** + * @return The ID of the session + */ + public String getId() { + return id; + } + + /** + * @return ID of the user which can be used when interacting with other APIs. + */ + public String getUserId() { + return userId; + } + + /** + * + * @return The date and time when the session was created + */ + public Date getCreatedAt() { + return createdAt; + } + + /** + * @return The date and time when the session was last updated + */ + public Date getUpdatedAt() { + return updatedAt; + } + + /** + * @return The date and time when the session was last authenticated + */ + public Date getAuthenticatedAt() { + return authenticatedAt; + } + + /** + * @return The date and time when the session will expire if idle + */ + public Date getIdleExpiresAt() { + return idleExpiresAt; + } + + /** + * @return The date and time when the session will expire + */ + public Date getExpiresAt() { + return expiresAt; + } + + /** + * @return Metadata related to the device used in the session + */ + public Device getDevice() { + return device; + } + + /** + * @return List of client details for the session + */ + public List getClients() { + return clients; + } + + /** + * @return Details about authentication signals obtained during the login flow + */ + public Authentication getAuthentication() { + return authentication; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/sessions/SessionsPage.java b/src/main/java/com/auth0/json/mgmt/sessions/SessionsPage.java new file mode 100644 index 000000000..10d58e9d5 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/sessions/SessionsPage.java @@ -0,0 +1,44 @@ +package com.auth0.json.mgmt.sessions; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * Class that represents a given Page of Sessions. Related to the {@link com.auth0.client.mgmt.UsersEntity} entity. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class SessionsPage { + @JsonProperty("total") + private Integer total; + + @JsonProperty("next") + private String next; + + @JsonProperty("sessions") + private List sessions; + + /** + * @return the total number of refresh tokens. This is only present when `include_totals` is passed as a query parameter. + */ + public Integer getTotal() { + return total; + } + + /** + * @return the token ID from which to start selection for a new page + */ + public String getNext() { + return next; + } + + /** + * @return the list of Sessions + */ + public List getSessions() { + return sessions; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/DailyStats.java b/src/main/java/com/auth0/json/mgmt/stats/DailyStats.java similarity index 96% rename from src/main/java/com/auth0/json/mgmt/DailyStats.java rename to src/main/java/com/auth0/json/mgmt/stats/DailyStats.java index 238039fc0..a673e5e31 100644 --- a/src/main/java/com/auth0/json/mgmt/DailyStats.java +++ b/src/main/java/com/auth0/json/mgmt/stats/DailyStats.java @@ -1,4 +1,4 @@ -package com.auth0.json.mgmt; +package com.auth0.json.mgmt.stats; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @@ -41,4 +41,4 @@ public Integer getLogins() { public Date getDate() { return date; } -} \ No newline at end of file +} diff --git a/src/main/java/com/auth0/json/mgmt/tenants/Clients.java b/src/main/java/com/auth0/json/mgmt/tenants/Clients.java new file mode 100644 index 000000000..49db8743e --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/tenants/Clients.java @@ -0,0 +1,35 @@ +package com.auth0.json.mgmt.tenants; + +import com.auth0.json.mgmt.tokenquota.ClientCredentials; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class Clients { + @JsonProperty("client_credentials") + private ClientCredentials clientCredentials; + + /** + * Default constructor for Clients. + */ + public Clients() { + } + + /** + * Constructor for Clients. + * + * @param clientCredentials the client credentials + */ + public Clients(ClientCredentials clientCredentials) { + this.clientCredentials = clientCredentials; + } + + /** + * @return the client credentials + */ + public ClientCredentials getClientCredentials() { + return clientCredentials; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/tenants/DefaultTokenQuota.java b/src/main/java/com/auth0/json/mgmt/tenants/DefaultTokenQuota.java new file mode 100644 index 000000000..2d5ae414d --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/tenants/DefaultTokenQuota.java @@ -0,0 +1,59 @@ +package com.auth0.json.mgmt.tenants; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class DefaultTokenQuota { + @JsonProperty("clients") + private Clients clients; + + @JsonProperty("organizations") + private Organizations organizations; + + /** + * Default constructor for DefaultTokenQuota. + */ + public DefaultTokenQuota() {} + + /** + * Constructor for DefaultTokenQuota. + * + * @param clients the clients + * @param organizations the organizations + */ + public DefaultTokenQuota(Clients clients, Organizations organizations) { + this.clients = clients; + this.organizations = organizations; + } + + /** + * @return the clients + */ + public Clients getClients() { + return clients; + } + + /** + * @param clients the clients to set + */ + public void setClients(Clients clients) { + this.clients = clients; + } + + /** + * @return the organizations + */ + public Organizations getOrganizations() { + return organizations; + } + + /** + * @param organizations the organizations to set + */ + public void setOrganizations(Organizations organizations) { + this.organizations = organizations; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/tenants/Mtls.java b/src/main/java/com/auth0/json/mgmt/tenants/Mtls.java new file mode 100644 index 000000000..e4c441e42 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/tenants/Mtls.java @@ -0,0 +1,34 @@ +package com.auth0.json.mgmt.tenants; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Represents the value of the {@code enable_endpoint_aliases} field of the {@link Tenant}. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class Mtls { + + @JsonProperty("enable_endpoint_aliases") + private Boolean enableEndpointAliases; + + /** + * @return the value of the {@code enable_endpoint_aliases} field + */ + public Boolean getEnableEndpointAliases() { + return enableEndpointAliases; + } + + /** + * Sets the value of the {@code enable_endpoint_aliases} field + * + * @param enableEndpointAliases the value of the {@code enable_endpoint_aliases} field + */ + public void setEnableEndpointAliases(Boolean enableEndpointAliases) { + this.enableEndpointAliases = enableEndpointAliases; + } + +} diff --git a/src/main/java/com/auth0/json/mgmt/tenants/Organizations.java b/src/main/java/com/auth0/json/mgmt/tenants/Organizations.java new file mode 100644 index 000000000..56c2d85d8 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/tenants/Organizations.java @@ -0,0 +1,34 @@ +package com.auth0.json.mgmt.tenants; + +import com.auth0.json.mgmt.tokenquota.ClientCredentials; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class Organizations { + @JsonProperty("client_credentials") + private ClientCredentials clientCredentials; + + /** + * Default constructor for Organizations. + */ + public Organizations() {} + + /** + * Constructor for Organizations. + * + * @param clientCredentials the client credentials + */ + public Organizations(ClientCredentials clientCredentials) { + this.clientCredentials = clientCredentials; + } + + /** + * @return the client credentials + */ + public ClientCredentials getClientCredentials() { + return clientCredentials; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/tenants/SessionCookie.java b/src/main/java/com/auth0/json/mgmt/tenants/SessionCookie.java new file mode 100644 index 000000000..0bc7db4e7 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/tenants/SessionCookie.java @@ -0,0 +1,26 @@ +package com.auth0.json.mgmt.tenants; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Represents the value of the {@code session_cookie} field of the {@link Tenant}. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class SessionCookie { + + @JsonProperty("mode") + private String mode; + + @JsonCreator + public SessionCookie(@JsonProperty("mode") String mode) { + this.mode = mode; + } + + public String getMode() { + return mode; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/tenants/Tenant.java b/src/main/java/com/auth0/json/mgmt/tenants/Tenant.java index bdae28055..817db0007 100644 --- a/src/main/java/com/auth0/json/mgmt/tenants/Tenant.java +++ b/src/main/java/com/auth0/json/mgmt/tenants/Tenant.java @@ -40,9 +40,30 @@ public class Tenant { @JsonProperty("session_lifetime") private Integer sessionLifetime; + @JsonProperty("session_cookie") + private SessionCookie sessionCookie; + @JsonProperty("idle_session_lifetime") private Integer idleSessionLifetime; + @JsonProperty("acr_values_supported") + private List acrValuesSupported; + + @JsonProperty("pushed_authorization_requests_supported") + private Boolean pushedAuthorizationRequestsSupported; + + @JsonProperty("remove_alg_from_jwks") + private Boolean removeAlgFromJwks; + + @JsonProperty("mtls") + private Mtls mtls; + + @JsonProperty("authorization_response_iss_parameter_supported") + private boolean authorizationResponseIssParameterSupported; + + @JsonProperty("default_token_quota") + private DefaultTokenQuota defaultTokenQuota; + /** * Getter for the change password page customization. * @@ -273,6 +294,21 @@ public Integer getSessionLifetime() { return sessionLifetime; } + /** + * @return the value of the session cookie. + */ + public SessionCookie getSessionCookie() { + return sessionCookie; + } + + /** + * Sets the value of the session cookie. + * @param sessionCookie the value of the session cookie to set. + */ + public void setSessionCookie(SessionCookie sessionCookie) { + this.sessionCookie = sessionCookie; + } + /** * Setter for the login session lifetime. This is how long the session will stay valid. Value is in hours. * @@ -302,4 +338,100 @@ public Integer getIdleSessionLifetime() { public void setIdleSessionLifetime(Integer idleSessionLifetime) { this.idleSessionLifetime = idleSessionLifetime; } + + /** + * @return the value of the {@code acr_values_supported} field + */ + public List getAcrValuesSupported() { + return acrValuesSupported; + } + + /** + * Sets the value of the {@code acr_values_supported} field + * + * @param acrValuesSupported the value of the {@code acr_values_supported_field} + */ + public void setAcrValuesSupported(List acrValuesSupported) { + this.acrValuesSupported = acrValuesSupported; + } + + /** + * @return the value of the {@code pushed_authorization_requests_supported} field. + */ + public Boolean getPushedAuthorizationRequestsSupported() { + return pushedAuthorizationRequestsSupported; + } + + /** + * Sets the value of the {@code pushed_authorization_requests_supported} field + * + * @param pushedAuthorizationRequestsSupported the value of the {@code pushed_authorization_requests_supported} field + */ + public void setPushedAuthorizationRequestsSupported(Boolean pushedAuthorizationRequestsSupported) { + this.pushedAuthorizationRequestsSupported = pushedAuthorizationRequestsSupported; + } + + /** + * @return the value of the {@code remove_alg_from_jwks} field + */ + public Boolean getRemoveAlgFromJwks() { + return removeAlgFromJwks; + } + + /** + * Sets the value of the {@code remove_alg_from_jwks} field + * + * @param removeAlgFromJwks the value of the {@code remove_alg_from_jwks} field + */ + public void setRemoveAlgFromJwks(Boolean removeAlgFromJwks) { + this.removeAlgFromJwks = removeAlgFromJwks; + } + + /** + * @return the value of the {@code mtls} field + */ + public Mtls getMtls() { + return mtls; + } + + /** + * Sets the value of the {@code mtls} field + * + * @param mtls the value of the {@code mtls} field + */ + public void setMtls(Mtls mtls) { + this.mtls = mtls; + } + + /** + * @return the value of the {@code authorization_response_iss_parameter_supported} field + */ + public boolean isAuthorizationResponseIssParameterSupported() { + return authorizationResponseIssParameterSupported; + } + + /** + * Sets the value of the {@code authorization_response_iss_parameter_supported} field + * + * @param authorizationResponseIssParameterSupported the value of the {@code authorization_response_iss_parameter_supported} field + */ + public void setAuthorizationResponseIssParameterSupported(boolean authorizationResponseIssParameterSupported) { + this.authorizationResponseIssParameterSupported = authorizationResponseIssParameterSupported; + } + + /** + * @return the value of the {@code default_token_quota} field + */ + public DefaultTokenQuota getDefaultTokenQuota() { + return defaultTokenQuota; + } + + /** + * Sets the value of the {@code default_token_quota} field + * + * @param defaultTokenQuota the value of the {@code default_token_quota} field + */ + public void setDefaultTokenQuota(DefaultTokenQuota defaultTokenQuota) { + this.defaultTokenQuota = defaultTokenQuota; + } } diff --git a/src/main/java/com/auth0/json/mgmt/EmailVerificationIdentity.java b/src/main/java/com/auth0/json/mgmt/tickets/EmailVerificationIdentity.java similarity index 97% rename from src/main/java/com/auth0/json/mgmt/EmailVerificationIdentity.java rename to src/main/java/com/auth0/json/mgmt/tickets/EmailVerificationIdentity.java index 7fb82422c..5c2a73c7d 100644 --- a/src/main/java/com/auth0/json/mgmt/EmailVerificationIdentity.java +++ b/src/main/java/com/auth0/json/mgmt/tickets/EmailVerificationIdentity.java @@ -1,4 +1,4 @@ -package com.auth0.json.mgmt; +package com.auth0.json.mgmt.tickets; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; diff --git a/src/main/java/com/auth0/json/mgmt/tickets/EmailVerificationTicket.java b/src/main/java/com/auth0/json/mgmt/tickets/EmailVerificationTicket.java index bcfc6633e..c33c10c48 100644 --- a/src/main/java/com/auth0/json/mgmt/tickets/EmailVerificationTicket.java +++ b/src/main/java/com/auth0/json/mgmt/tickets/EmailVerificationTicket.java @@ -1,7 +1,6 @@ package com.auth0.json.mgmt.tickets; -import com.auth0.json.mgmt.EmailVerificationIdentity; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; diff --git a/src/main/java/com/auth0/json/mgmt/tokenquota/ClientCredentials.java b/src/main/java/com/auth0/json/mgmt/tokenquota/ClientCredentials.java new file mode 100644 index 000000000..b7d52ef4c --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/tokenquota/ClientCredentials.java @@ -0,0 +1,81 @@ +package com.auth0.json.mgmt.tokenquota; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ClientCredentials { + @JsonProperty("per_day") + private Integer perDay; + @JsonProperty("per_hour") + private Integer perHour; + @JsonProperty("enforce") + private boolean enforce; + /** + * Default constructor for ClientCredentials. + */ + public ClientCredentials() {} + + /** + * Constructor for ClientCredentials. + * + * @param perDay the number of client credentials allowed per day + * @param perHour the number of client credentials allowed per hour + * @param enforce true if the quota is enforced, false otherwise + */ + public ClientCredentials(Integer perDay, Integer perHour, boolean enforce) { + this.perDay = perDay; + this.perHour = perHour; + this.enforce = enforce; + } + + /** + * @return the number of client credentials allowed per day + */ + public Integer getPerDay() { + return perDay; + } + + /** + * Sets the number of client credentials allowed per day. + * + * @param perDay the number of client credentials allowed per day + */ + public void setPerDay(Integer perDay) { + this.perDay = perDay; + } + + /** + * @return the number of client credentials allowed per hour + */ + public Integer getPerHour() { + return perHour; + } + + /** + * Sets the number of client credentials allowed per hour. + * + * @param perHour the number of client credentials allowed per hour + */ + public void setPerHour(Integer perHour) { + this.perHour = perHour; + } + + /** + * @return true if the quota is enforced, false otherwise + */ + public boolean isEnforce() { + return enforce; + } + + /** + * Sets whether the quota is enforced. + * + * @param enforce true to enforce the quota, false otherwise + */ + public void setEnforce(boolean enforce) { + this.enforce = enforce; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/tokenquota/TokenQuota.java b/src/main/java/com/auth0/json/mgmt/tokenquota/TokenQuota.java new file mode 100644 index 000000000..e11dadac2 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/tokenquota/TokenQuota.java @@ -0,0 +1,32 @@ +package com.auth0.json.mgmt.tokenquota; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class TokenQuota { + @JsonProperty("client_credentials") + private ClientCredentials clientCredentials; + + /** + * Default constructor for Clients. + */ + public TokenQuota() {} + /** + * Constructor for Clients. + * + * @param clientCredentials the client credentials + */ + public TokenQuota(ClientCredentials clientCredentials) { + this.clientCredentials = clientCredentials; + } + + /** + * @return the client credentials + */ + public ClientCredentials getClientCredentials() { + return clientCredentials; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/userAttributeProfiles/ListUserAttributeProfileTemplate.java b/src/main/java/com/auth0/json/mgmt/userAttributeProfiles/ListUserAttributeProfileTemplate.java new file mode 100644 index 000000000..34d108839 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/userAttributeProfiles/ListUserAttributeProfileTemplate.java @@ -0,0 +1,32 @@ +package com.auth0.json.mgmt.userAttributeProfiles; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ListUserAttributeProfileTemplate { + @JsonProperty("user_attribute_profile_templates") + private List userAttributeProfileTemplateResponses; + + /** + * Gets the user attribute profile templates + * @return the user attribute profile templates + */ + @JsonProperty("user_attribute_profile_templates") + public List getUserAttributeProfileTemplates() { + return userAttributeProfileTemplateResponses; + } + + /** + * Sets the user attribute profile templates + * @param userAttributeProfileTemplateResponses the user attribute profile templates + */ + @JsonProperty("user_attribute_profile_templates") + public void setUserAttributeProfileTemplates(List userAttributeProfileTemplateResponses) { + this.userAttributeProfileTemplateResponses = userAttributeProfileTemplateResponses; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/userAttributeProfiles/OidcMapping.java b/src/main/java/com/auth0/json/mgmt/userAttributeProfiles/OidcMapping.java new file mode 100644 index 000000000..363d53d24 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/userAttributeProfiles/OidcMapping.java @@ -0,0 +1,34 @@ +package com.auth0.json.mgmt.userAttributeProfiles; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class OidcMapping { + @JsonProperty("mapping") + private String mapping; + @JsonProperty("display_name") + private String displayName; + + @JsonProperty("mapping") + public String getMapping() { + return mapping; + } + + @JsonProperty("mapping") + public void setMapping(String mapping) { + this.mapping = mapping; + } + + @JsonProperty("display_name") + public String getDisplayName() { + return displayName; + } + + @JsonProperty("display_name") + public void setDisplayName(String displayName) { + this.displayName = displayName; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/userAttributeProfiles/StrategyOverridesUserAttributes.java b/src/main/java/com/auth0/json/mgmt/userAttributeProfiles/StrategyOverridesUserAttributes.java new file mode 100644 index 000000000..221cf0288 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/userAttributeProfiles/StrategyOverridesUserAttributes.java @@ -0,0 +1,73 @@ +package com.auth0.json.mgmt.userAttributeProfiles; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class StrategyOverridesUserAttributes { + + @JsonProperty("oidc_mapping") + private OidcMapping oidcMapping; + @JsonProperty("saml_mapping") + private List samlMapping; + @JsonProperty("scim_mapping") + private String scimMapping; + + /** + * OIDC mapping. + * @return the OIDC mapping + */ + @JsonProperty("oidc_mapping") + public OidcMapping getOidcMapping() { + return oidcMapping; + } + + /** + * Sets the OIDC mapping. + * @param oidcMapping the OIDC mapping + */ + @JsonProperty("oidc_mapping") + public void setOidcMapping(OidcMapping oidcMapping) { + this.oidcMapping = oidcMapping; + } + + /** + * SAML mapping. + * @return the SAML mapping + */ + @JsonProperty("saml_mapping") + public List getSamlMapping() { + return samlMapping; + } + + /** + * Sets the SAML mapping. + * @param samlMapping the SAML mapping + */ + @JsonProperty("saml_mapping") + public void setSamlMapping(List samlMapping) { + this.samlMapping = samlMapping; + } + + /** + * SCIM mapping. + * @return the SCIM mapping + */ + @JsonProperty("scim_mapping") + public String getScimMapping() { + return scimMapping; + } + + /** + * Sets the SCIM mapping. + * @param scimMapping the SCIM mapping + */ + @JsonProperty("scim_mapping") + public void setScimMapping(String scimMapping) { + this.scimMapping = scimMapping; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/userAttributeProfiles/StrategyOverridesUserId.java b/src/main/java/com/auth0/json/mgmt/userAttributeProfiles/StrategyOverridesUserId.java new file mode 100644 index 000000000..9e2543cd5 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/userAttributeProfiles/StrategyOverridesUserId.java @@ -0,0 +1,72 @@ +package com.auth0.json.mgmt.userAttributeProfiles; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class StrategyOverridesUserId { + @JsonProperty("oidc_mapping") + private String oidcMapping; + @JsonProperty("saml_mapping") + private List samlMapping; + @JsonProperty("scim_mapping") + private String scimMapping; + + /** + * OIDC mapping. + * @return the OIDC mapping + */ + @JsonProperty("oidc_mapping") + public String getOidcMapping() { + return oidcMapping; + } + + /** + * Sets the OIDC mapping. + * @param oidcMapping the OIDC mapping + */ + @JsonProperty("oidc_mapping") + public void setOidcMapping(String oidcMapping) { + this.oidcMapping = oidcMapping; + } + + /** + * SAML mapping. + * @return the SAML mapping + */ + @JsonProperty("saml_mapping") + public List getSamlMapping() { + return samlMapping; + } + + /** + * Sets the SAML mapping. + * @param samlMapping the SAML mapping + */ + @JsonProperty("saml_mapping") + public void setSamlMapping(List samlMapping) { + this.samlMapping = samlMapping; + } + + /** + * SCIM mapping. + * @return the SCIM mapping + */ + @JsonProperty("scim_mapping") + public String getScimMapping() { + return scimMapping; + } + + /** + * Sets the SCIM mapping. + * @param scimMapping the SCIM mapping + */ + @JsonProperty("scim_mapping") + public void setScimMapping(String scimMapping) { + this.scimMapping = scimMapping; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/userAttributeProfiles/UserAttributeProfile.java b/src/main/java/com/auth0/json/mgmt/userAttributeProfiles/UserAttributeProfile.java new file mode 100644 index 000000000..f0e9d5587 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/userAttributeProfiles/UserAttributeProfile.java @@ -0,0 +1,84 @@ +package com.auth0.json.mgmt.userAttributeProfiles; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Map; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class UserAttributeProfile { + + @JsonProperty("id") + private String id; + @JsonProperty("name") + private String name; + @JsonProperty("user_id") + private UserId userId; + @JsonProperty("user_attributes") + private Map userAttributes; + + /** + * Gets the user attribute profile ID. + * @return the user attribute profile ID + */ + @JsonProperty("id") + public String getId() { + return id; + } + + /** + * Sets the user attribute profile ID. + * @return the user attribute profile ID + */ + @JsonProperty("name") + public String getName() { + return name; + } + + /** + * Sets the user attribute profile name. + * @param name the user attribute profile name + */ + @JsonProperty("name") + public void setName(String name) { + this.name = name; + } + + /** + * Gets the user ID configuration. + * @return the user ID configuration + */ + @JsonProperty("user_id") + public UserId getUserId() { + return userId; + } + + /** + * Sets the user ID configuration. + * @param userId the user ID configuration + */ + @JsonProperty("user_id") + public void setUserId(UserId userId) { + this.userId = userId; + } + + /** + * Gets the user attributes configuration. + * @return the user attributes configuration + */ + @JsonProperty("user_attributes") + public Map getUserAttributes() { + return userAttributes; + } + + /** + * Sets the user attributes configuration. + * @param userAttributes the user attributes configuration + */ + @JsonProperty("user_attributes") + public void setUserAttributes(Map userAttributes) { + this.userAttributes = userAttributes; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/userAttributeProfiles/UserAttributeProfilePage.java b/src/main/java/com/auth0/json/mgmt/userAttributeProfiles/UserAttributeProfilePage.java new file mode 100644 index 000000000..3cdca2a6d --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/userAttributeProfiles/UserAttributeProfilePage.java @@ -0,0 +1,26 @@ +package com.auth0.json.mgmt.userAttributeProfiles; + +import com.auth0.json.mgmt.Page; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; + +import java.util.List; + +@SuppressWarnings({"unused", "WeakerAccess"}) +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonDeserialize(using = UserAttributeProfilePageDeserializer.class) +public class UserAttributeProfilePage extends Page { + public UserAttributeProfilePage(List items) { + super(items); + } + + protected UserAttributeProfilePage(Integer start, Integer length, Integer total, Integer limit, List items) { + super(start, length, total, limit, items); + } + + protected UserAttributeProfilePage(Integer start, Integer length, Integer total, Integer limit, String next, List items){ + super(start, length, total, limit, next, items); + } +} diff --git a/src/main/java/com/auth0/json/mgmt/userAttributeProfiles/UserAttributeProfilePageDeserializer.java b/src/main/java/com/auth0/json/mgmt/userAttributeProfiles/UserAttributeProfilePageDeserializer.java new file mode 100644 index 000000000..d4a89bf7b --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/userAttributeProfiles/UserAttributeProfilePageDeserializer.java @@ -0,0 +1,28 @@ +package com.auth0.json.mgmt.userAttributeProfiles; + +import com.auth0.json.mgmt.PageDeserializer; + +import java.util.List; + + +@SuppressWarnings({"unused", "WeakerAccess"}) +class UserAttributeProfilePageDeserializer extends PageDeserializer { + UserAttributeProfilePageDeserializer() { + super(UserAttributeProfile.class, "user_attribute_profiles"); + } + + @Override + protected UserAttributeProfilePage createPage(List items) { + return new UserAttributeProfilePage(items); + } + + @Override + protected UserAttributeProfilePage createPage(Integer start, Integer length, Integer total, Integer limit, List items) { + return new UserAttributeProfilePage(start, length, total, limit, items); + } + + @Override + protected UserAttributeProfilePage createPage(Integer start, Integer length, Integer total, Integer limit, String next, List items) { + return new UserAttributeProfilePage(start, length, total, limit, next, items); + } +} diff --git a/src/main/java/com/auth0/json/mgmt/userAttributeProfiles/UserAttributeProfileTemplate.java b/src/main/java/com/auth0/json/mgmt/userAttributeProfiles/UserAttributeProfileTemplate.java new file mode 100644 index 000000000..1934a521d --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/userAttributeProfiles/UserAttributeProfileTemplate.java @@ -0,0 +1,71 @@ +package com.auth0.json.mgmt.userAttributeProfiles; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Class that represents a User Attribute Profile Template object. Related to + * the {@link com.auth0.client.mgmt.UserAttributeProfilesEntity} entity. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class UserAttributeProfileTemplate { + + @JsonProperty("id") + private String id; + @JsonProperty("display_name") + private String displayName; + @JsonProperty("template") + private UserAttributeProfile template; + + /** + * Getter for the template ID. + * + * @return the template ID. + */ + @JsonProperty("id") + public String getId() { + return id; + } + + /** + * Getter for the display name. + * + * @return the display name. + */ + @JsonProperty("display_name") + public String getDisplayName() { + return displayName; + } + + /** + * Setter for the display name. + * + * @param displayName the display name to set. + */ + @JsonProperty("display_name") + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + /** + * Getter for the template. + * + * @return the template. + */ + @JsonProperty("template") + public UserAttributeProfile getTemplate() { + return template; + } + + /** + * Setter for the template. + * + * @param template the template to set. + */ + @JsonProperty("template") + public void setTemplate(UserAttributeProfile template) { + this.template = template; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/userAttributeProfiles/UserAttributes.java b/src/main/java/com/auth0/json/mgmt/userAttributeProfiles/UserAttributes.java new file mode 100644 index 000000000..cd1276084 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/userAttributeProfiles/UserAttributes.java @@ -0,0 +1,174 @@ +package com.auth0.json.mgmt.userAttributeProfiles; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; +import java.util.Map; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class UserAttributes { + @JsonProperty("description") + private String description; + @JsonProperty("label") + private String label; + @JsonProperty("profile_required") + private boolean profileRequired; + @JsonProperty("auth0_mapping") + private String auth0Mapping; + @JsonProperty("oidc_mapping") + private OidcMapping oidcMapping; + @JsonProperty("saml_mapping") + private List samlMapping; + @JsonProperty("scim_mapping") + private String scimMapping; + @JsonProperty("strategy_overrides") + private Map strategyOverrides; + + /** + * Description of the user attribute. + * @return the description + */ + @JsonProperty("description") + public String getDescription() { + return description; + } + + /** + * Sets the description of the user attribute. + * @param description + */ + @JsonProperty("description") + public void setDescription(String description) { + this.description = description; + } + + /** + * Label of the user attribute. + * @return the label + */ + @JsonProperty("label") + public String getLabel() { + return label; + } + + /** + * Sets the label of the user attribute. + * @param label the label + */ + @JsonProperty("label") + public void setLabel(String label) { + this.label = label; + } + + /** + * Indicates if the user attribute is required in the profile. + * @return true if the user attribute is required in the profile, false otherwise + */ + @JsonProperty("profile_required") + public boolean isProfileRequired() { + return profileRequired; + } + + /** + * Sets if the user attribute is required in the profile. + * @param profileRequired true if the user attribute is required in the profile, false otherwise + */ + @JsonProperty("profile_required") + public void setProfileRequired(boolean profileRequired) { + this.profileRequired = profileRequired; + } + + /** + * Auth0 mapping. + * @return the Auth0 mapping + */ + @JsonProperty("auth0_mapping") + public String getAuth0Mapping() { + return auth0Mapping; + } + + /** + * Sets the Auth0 mapping. + * @param auth0Mapping the Auth0 mapping + */ + @JsonProperty("auth0_mapping") + public void setAuth0Mapping(String auth0Mapping) { + this.auth0Mapping = auth0Mapping; + } + + /** + * OIDC mapping. + * @return the OIDC mapping + */ + @JsonProperty("oidc_mapping") + public OidcMapping getOidcMapping() { + return oidcMapping; + } + + /** + * Sets the OIDC mapping. + * @param oidcMapping the OIDC mapping + */ + @JsonProperty("oidc_mapping") + public void setOidcMapping(OidcMapping oidcMapping) { + this.oidcMapping = oidcMapping; + } + + /** + * SAML mapping. + * @return the SAML mapping + */ + @JsonProperty("saml_mapping") + public List getSamlMapping() { + return samlMapping; + } + + /** + * Sets the SAML mapping. + * @param samlMapping the SAML mapping + */ + @JsonProperty("saml_mapping") + public void setSamlMapping(List samlMapping) { + this.samlMapping = samlMapping; + } + + /** + * SCIM mapping. + * @return the SCIM mapping + */ + @JsonProperty("scim_mapping") + public String getScimMapping() { + return scimMapping; + } + + /** + * Sets the SCIM mapping. + * @param scimMapping the SCIM mapping + */ + @JsonProperty("scim_mapping") + public void setScimMapping(String scimMapping) { + this.scimMapping = scimMapping; + } + + /** + * Strategy overrides mapping. + * @return the strategy overrides mapping + */ + @JsonProperty("strategy_overrides") + public Map getStrategyOverrides() { + return strategyOverrides; + } + + /** + * Sets the strategy overrides mapping. + * @param strategyOverrides the strategy overrides mapping + */ + @JsonProperty("strategy_overrides") + public void setStrategyOverrides(Map strategyOverrides) { + this.strategyOverrides = strategyOverrides; + } +} + diff --git a/src/main/java/com/auth0/json/mgmt/userAttributeProfiles/UserId.java b/src/main/java/com/auth0/json/mgmt/userAttributeProfiles/UserId.java new file mode 100644 index 000000000..41391d4e2 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/userAttributeProfiles/UserId.java @@ -0,0 +1,93 @@ +package com.auth0.json.mgmt.userAttributeProfiles; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; +import java.util.Map; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class UserId { + @JsonProperty("oidc_mapping") + private String oidcMapping; + @JsonProperty("saml_mapping") + private List samlMapping; + @JsonProperty("scim_mapping") + private String scimMapping; + @JsonProperty("strategy_overrides") + private Map strategyOverrides; + + /** + * OIDC mapping. + * @return the OIDC mapping + */ + @JsonProperty("oidc_mapping") + public String getOidcMapping() { + return oidcMapping; + } + + /** + * Sets the OIDC mapping. + * @param oidcMapping the OIDC mapping + */ + @JsonProperty("oidc_mapping") + public void setOidcMapping(String oidcMapping) { + this.oidcMapping = oidcMapping; + } + + /** + * SAML mapping. + * @return the SAML mapping + */ + @JsonProperty("saml_mapping") + public List getSamlMapping() { + return samlMapping; + } + + /** + * Sets the SAML mapping. + * @param samlMapping the SAML mapping + */ + @JsonProperty("saml_mapping") + public void setSamlMapping(List samlMapping) { + this.samlMapping = samlMapping; + } + + /** + * SCIM mapping. + * @return the SCIM mapping + */ + @JsonProperty("scim_mapping") + public String getScimMapping() { + return scimMapping; + } + + /** + * Sets the SCIM mapping. + * @param scimMapping the SCIM mapping + */ + @JsonProperty("scim_mapping") + public void setScimMapping(String scimMapping) { + this.scimMapping = scimMapping; + } + + /** + * Strategy overrides mapping. + * @return the strategy overrides mapping + */ + @JsonProperty("strategy_overrides") + public Map getStrategyOverrides() { + return strategyOverrides; + } + + /** + * Sets the strategy overrides mapping. + * @param strategyOverrides the strategy overrides mapping + */ + @JsonProperty("strategy_overrides") + public void setStrategyOverrides(Map strategyOverrides) { + this.strategyOverrides = strategyOverrides; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/users/authenticationmethods/AuthMethod.java b/src/main/java/com/auth0/json/mgmt/users/authenticationmethods/AuthMethod.java new file mode 100644 index 000000000..2cd1c4e90 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/users/authenticationmethods/AuthMethod.java @@ -0,0 +1,23 @@ +package com.auth0.json.mgmt.users.authenticationmethods; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class AuthMethod { + + @JsonProperty("id") + private String id; + @JsonProperty("type") + private String type; + + public String getId() { + return id; + } + + public String getType() { + return type; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/users/authenticationmethods/AuthenticationMethod.java b/src/main/java/com/auth0/json/mgmt/users/authenticationmethods/AuthenticationMethod.java new file mode 100644 index 000000000..8b17b8f48 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/users/authenticationmethods/AuthenticationMethod.java @@ -0,0 +1,290 @@ +package com.auth0.json.mgmt.users.authenticationmethods; + +import com.fasterxml.jackson.annotation.*; + +import java.util.Date; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class AuthenticationMethod { + @JsonProperty("id") + private String id; + @JsonProperty("type") + private String type; + @JsonProperty("confirmed") + private Boolean confirmed; + @JsonProperty("name") + private String name; + @JsonProperty("link_id") + private String linkId; + @JsonProperty("phone_number") + private String phoneNumber; + @JsonProperty("email") + private String email; + @JsonProperty("key_id") + private String keyId; + @JsonProperty("public_key") + private String publicKey; + @JsonProperty("created_at") + private Date createdAt; + @JsonProperty("enrolled_at") + private Date enrolledAt; + @JsonProperty("last_auth_at") + private Date lastAuthedAt; + @JsonProperty("totp_secret") + private String totpSecret; + @JsonProperty("preferred_authentication_method") + private String preferredAuthenticationMethod; + @JsonProperty("relying_party_identifier") + private String relyingPartyIdentifier; + @JsonProperty("authentication_methods") + private List authenticationMethods; + @JsonProperty("credential_device_type") + private String credentialDeviceType; + @JsonProperty("credential_backed_up") + private Boolean credentialBackedUp; + @JsonProperty("identity_user_id") + private String identityUserId; + @JsonProperty("user_agent") + private String userAgent; + + /** + * Create a new instance. + */ + @JsonCreator + public AuthenticationMethod() { + } + + /** + * @return the ID of this enrollment. + */ + public String getId() { + return id; + } + + /** + * @return the type of this enrollment + */ + public String getType() { + return type; + } + + /** + * Sets the type of this enrollment + * Should be ["phone" or "email" or "totp" or "webauthn-roaming"] + * + * @param type the type of the enrollment. + */ + public void setType(String type) { + this.type = type; + } + + /** + * @return the enrollment status + */ + public Boolean getConfirmed() { + return confirmed; + } + + /** + * @return A human-readable label to identify the authentication method. + */ + public String getName() { + return name; + } + + /** + * Set a human-readable label to identify the authentication method. + * + * @param name A human-readable label to identify the authentication method. + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return the indication that the authenticator is linked to another authenticator + */ + public String getLinkId() { + return linkId; + } + + /** + * @return The destination phone number used to send verification codes via text and voice. Applies to phone authentication methods only. + */ + public String getPhoneNumber() { + return phoneNumber; + } + + /** + * Set the destination phone number used to send verification codes via text and voice. + * Applies to phone authentication methods only. + * + * @param phoneNumber The destination phone number used to send verification codes via text and voice. + */ + public void setPhoneNumber(String phoneNumber) { + this.phoneNumber = phoneNumber; + } + + /** + * @return The email address used to send verification messages. Applies to email authentication methods only. + */ + public String getEmail() { + return email; + } + + /** + * Set the email address used to send verification messages. Applies to email authentication methods only. + * @param email The email address used to send verification messages. + */ + public void setEmail(String email) { + this.email = email; + } + + /** + * @return The id of the credential. Applies to email webauthn authenticators only. + */ + public String getKeyId() { + return keyId; + } + + /** + * The id of the credential. Applies to email webauthn authenticators only. + * @param keyId The id of the credential. + */ + public void setKeyId(String keyId) { + this.keyId = keyId; + } + + /** + * @return The public key. Applies to email webauthn authenticators only. + */ + public String getPublicKey() { + return publicKey; + } + + /** + * Set the public key. Applies to email webauthn authenticators only. + * @param publicKey The public key. Applies to email webauthn authenticators only. + */ + public void setPublicKey(String publicKey) { + this.publicKey = publicKey; + } + + /** + * + * @return Authenticator creation date + */ + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JsonProperty("created_at") + public Date getCreatedAt() { + return createdAt; + } + + /** + * @return Enrollment date + */ + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JsonProperty("enrolled_at") + public Date getEnrolledAt() { + return enrolledAt; + } + + /** + * @return Last authentication + */ + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JsonProperty("last_auth_at") + public Date getLastAuthedAt() { + return lastAuthedAt; + } + + /** + * @return The base32 encoded secret for TOTP generation. Applies to totp authentication methods only. + */ + public String getTotpSecret() { + return totpSecret; + } + + /** + * Set the base32 encoded secret for TOTP generation. Applies to totp authentication methods only. + * @param totpSecret The base32 encoded secret for TOTP generation. + */ + public void setTotpSecret(String totpSecret) { + this.totpSecret = totpSecret; + } + + /** + * @return Preferred phone authentication method. + */ + public String getPreferredAuthenticationMethod() { + return preferredAuthenticationMethod; + } + + /** + * Set the preferred phone authentication method. + * @param preferredAuthenticationMethod Preferred phone authentication method. + */ + public void setPreferredAuthenticationMethod(String preferredAuthenticationMethod) { + this.preferredAuthenticationMethod = preferredAuthenticationMethod; + } + + /** + * @return The relying party identifier. Applies to email webauthn authenticators only. + */ + public String getRelyingPartyIdentifier() { + return relyingPartyIdentifier; + } + + /** + * Set the relying party identifier. Applies to email webauthn authenticators only. + * @param relyingPartyIdentifier The relying party identifier. Applies to email webauthn authenticators only. + */ + public void setRelyingPartyIdentifier(String relyingPartyIdentifier) { + this.relyingPartyIdentifier = relyingPartyIdentifier; + } + + /** + * @return list of authentication methods + */ + public List getAuthenticationMethods() { + return authenticationMethods; + } + + /** + * Applies to passkeys only. + * + * @return The kind of device the credential is stored on as defined by backup eligibility. "single_device" credentials cannot be backed up and synced to another device, "multi_device" credentials can be backed up if enabled by the end-user. + */ + public String getCredentialDeviceType() { + return credentialDeviceType; + } + + /** + * Applies to passkeys only. + * + * @return Whether the credential was backed up. + */ + public Boolean getCredentialBackedUp() { + return credentialBackedUp; + } + + /** + * Applies to passkeys only. + * + * @return The ID of the user identity linked with the authentication method. + */ + public String getIdentityUserId() { + return identityUserId; + } + + /** + * Applies to passkeys only. + * + * @return The user-agent of the browser used to create the passkey. + */ + public String getUserAgent() { + return userAgent; + } +} diff --git a/src/main/java/com/auth0/json/mgmt/users/authenticationmethods/AuthenticationMethodsPage.java b/src/main/java/com/auth0/json/mgmt/users/authenticationmethods/AuthenticationMethodsPage.java new file mode 100644 index 000000000..7ad7b34e5 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/users/authenticationmethods/AuthenticationMethodsPage.java @@ -0,0 +1,34 @@ +package com.auth0.json.mgmt.users.authenticationmethods; + +import com.auth0.json.mgmt.Page; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; + +import java.util.List; + +/** + * Represents a page of an AuthenticationMethod. + * @see AuthenticationMethod + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonDeserialize(using = AuthenticationMethodsPageDeserializer.class) +public class AuthenticationMethodsPage extends Page { + public AuthenticationMethodsPage(List items) { + super(items); + } + + /** + * @deprecated use {@linkplain AuthenticationMethodsPage#AuthenticationMethodsPage(Integer, Integer, Integer, Integer, String, List)} instead. + */ + @Deprecated + public AuthenticationMethodsPage(Integer start, Integer length, Integer total, Integer limit, List items) { + super(start, length, total, limit, items); + } + + public AuthenticationMethodsPage(Integer start, Integer length, Integer total, Integer limit, String next, List items) { + super(start, length, total, limit, next, items); + } +} + diff --git a/src/main/java/com/auth0/json/mgmt/users/authenticationmethods/AuthenticationMethodsPageDeserializer.java b/src/main/java/com/auth0/json/mgmt/users/authenticationmethods/AuthenticationMethodsPageDeserializer.java new file mode 100644 index 000000000..3472e9d63 --- /dev/null +++ b/src/main/java/com/auth0/json/mgmt/users/authenticationmethods/AuthenticationMethodsPageDeserializer.java @@ -0,0 +1,32 @@ +package com.auth0.json.mgmt.users.authenticationmethods; + +import com.auth0.json.mgmt.PageDeserializer; + +import java.util.List; + +/** + * Parses a paged response into its {@linkplain AuthenticationMethodsPage} representation. + */ +public class AuthenticationMethodsPageDeserializer extends PageDeserializer { + + protected AuthenticationMethodsPageDeserializer() { + super(AuthenticationMethod.class, "authenticators"); + } + + @Override + protected AuthenticationMethodsPage createPage(List items) { + return new AuthenticationMethodsPage(items); + } + + @Override + @SuppressWarnings("deprecation") + protected AuthenticationMethodsPage createPage(Integer start, Integer length, Integer total, Integer limit, List items) { + return new AuthenticationMethodsPage(start, length, total, limit, items); + } + + @Override + protected AuthenticationMethodsPage createPage(Integer start, Integer length, Integer total, Integer limit, String next, List items) { + return new AuthenticationMethodsPage(start, length, total, limit, next, items); + } +} + diff --git a/src/main/java/com/auth0/net/AuthRequest.java b/src/main/java/com/auth0/net/AuthRequest.java deleted file mode 100644 index 7e3523a6c..000000000 --- a/src/main/java/com/auth0/net/AuthRequest.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.auth0.net; - -import com.auth0.json.auth.TokenHolder; - -/** - * Class that represents an OAuth 2.0 Authentication/Authorization request. The execution will return a {@link TokenHolder}. - */ -public interface AuthRequest extends Request { - - /** - * Setter for the realm value to request - * - * @param realm the realm to request - * @return this request instance. - */ - AuthRequest setRealm(String realm); - - /** - * Setter for the audience value to request - * - * @param audience the audience to request - * @return this request instance. - */ - AuthRequest setAudience(String audience); - - /** - * Setter for the scope value to request - * - * @param scope the scope to request - * @return this request instance. - */ - AuthRequest setScope(String scope); -} diff --git a/src/main/java/com/auth0/net/BaseRequest.java b/src/main/java/com/auth0/net/BaseRequest.java index bd3d0d1c3..2ddcfc5f0 100644 --- a/src/main/java/com/auth0/net/BaseRequest.java +++ b/src/main/java/com/auth0/net/BaseRequest.java @@ -1,27 +1,127 @@ package com.auth0.net; +import com.auth0.client.mgmt.TokenProvider; +import com.auth0.exception.APIException; import com.auth0.exception.Auth0Exception; -import okhttp3.Call; -import okhttp3.Callback; -import okhttp3.OkHttpClient; -import okhttp3.Response; -import org.jetbrains.annotations.NotNull; +import com.auth0.exception.RateLimitException; +import com.auth0.json.ObjectMapperProvider; +import com.auth0.net.client.*; +import com.auth0.utils.HttpResponseHeadersUtils; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.type.MapType; import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; import java.util.concurrent.CompletableFuture; -public abstract class BaseRequest implements Request { - private final OkHttpClient client; +/** + * A request class that is able to interact fluently with the Auth0 server. + * The default content type of this request is "application/json". + *

+ * This class is not thread-safe: + * It makes use of {@link HashMap} for storing the parameters. Make sure to not modify headers or the parameters + * from a different or un-synchronized thread. + * + * @param The type expected to be received as part of the response. + */ +public class BaseRequest implements Request { - BaseRequest(OkHttpClient client) { + private static final String CONTENT_TYPE_APPLICATION_JSON = "application/json"; + + private final String url; + private final HttpMethod method; + private final ObjectMapper mapper; + private final Map headers; + private final TypeReference tType; + private final Map parameters; + private Object body; + + private static final int STATUS_CODE_TOO_MANY_REQUEST = 429; + + private final Auth0HttpClient client; + private final TokenProvider tokenProvider; + + BaseRequest(Auth0HttpClient client, TokenProvider tokenProvider, String url, HttpMethod method, ObjectMapper mapper, TypeReference tType) { this.client = client; + this.tokenProvider = tokenProvider; + this.url = url; + this.method = method; + this.mapper = mapper; + this.headers = new HashMap<>(); + this.tType = tType; + this.parameters = new HashMap<>(); + } + + public BaseRequest(Auth0HttpClient client, TokenProvider tokenProvider, String url, HttpMethod method, TypeReference tType) { + this(client, tokenProvider, url, method, ObjectMapperProvider.getMapper(), tType); + } + + protected Auth0HttpRequest createRequest(String apiToken) throws Auth0Exception { + HttpRequestBody body; + try { + body = this.createRequestBody(); + } catch (IOException e) { + throw new Auth0Exception("Couldn't create the request body.", e); + } + headers.put("Content-Type", getContentType()); + // Auth APIs don't take tokens + if (Objects.nonNull(apiToken)) { + headers.put("Authorization", "Bearer " + apiToken); + } + Auth0HttpRequest request = Auth0HttpRequest.newBuilder(url, method) + .withBody(body) + .withHeaders(headers) + .build(); + + return request; } - protected abstract okhttp3.Request createRequest() throws Auth0Exception; + protected T parseResponseBody(Auth0HttpResponse response) throws Auth0Exception { + if (!response.isSuccessful()) { + throw createResponseException(response); + } + + try { + return readResponseBody(response); + } catch (IOException e) { + throw new APIException("Failed to parse the response body.", response.getCode(), e); + } + } + + /** + * Responsible for creating the payload that will be set as body on this request. + * + * @return the body to send as part of the request. + * @throws IOException if an error is raised during the creation of the body. + */ + @SuppressWarnings("deprecation") + protected HttpRequestBody createRequestBody() throws IOException { + if (body == null && parameters.isEmpty()) { + return null; + } + byte[] jsonBody = mapper.writeValueAsBytes(body != null ? body : parameters); + return HttpRequestBody.create(CONTENT_TYPE_APPLICATION_JSON, jsonBody); + } - protected abstract T parseResponse(Response response) throws Auth0Exception; + /** + * Responsible for parsing the payload that is received as part of the response. + * + * @param response the received response. The body buffer will automatically closed. + * @return the instance of type T, result of interpreting the payload. + * @throws IOException if an error is raised during the parsing of the body. + */ + protected T readResponseBody(Auth0HttpResponse response) throws IOException { + String payload = response.getBody(); + return mapper.readValue(payload, tType); + } + protected Map getParameters() { + return this.parameters; + } /** * Executes this request. * @@ -29,46 +129,145 @@ public abstract class BaseRequest implements Request { * @throws Auth0Exception if the request execution fails. */ @Override - public T execute() throws Auth0Exception { - okhttp3.Request request = createRequest(); - try (Response response = client.newCall(request).execute()) { - return parseResponse(response); + public com.auth0.net.Response execute() throws Auth0Exception { + String apiToken = null; + if (Objects.nonNull(tokenProvider)) { + apiToken = tokenProvider.getToken(); + } + Auth0HttpRequest request = createRequest(apiToken); + try { + Auth0HttpResponse response = client.sendRequest(request); + T body = parseResponseBody(response); + return new ResponseImpl(response.getHeaders(), body, response.getCode()); } catch (Auth0Exception e) { throw e; - } catch (IOException e) { - throw new Auth0Exception("Failed to execute request", e); + } catch (IOException ioe) { + throw new Auth0Exception("Failed to execute the request", ioe); } } @Override - public CompletableFuture executeAsync() { - final CompletableFuture future = new CompletableFuture(); + public CompletableFuture> executeAsync() { + final CompletableFuture> future = new CompletableFuture<>(); + + if (Objects.nonNull(tokenProvider)) { + return tokenProvider.getTokenAsync().thenCompose(token -> { + try { + return client.sendRequestAsync(createRequest(token)) + .thenCompose(this::getResponseFuture); + } catch (Auth0Exception e) { + future.completeExceptionally(e); + return future; + } + }); + } - okhttp3.Request request; try { - request = createRequest(); + return client.sendRequestAsync(createRequest(null)) + .thenCompose(this::getResponseFuture); } catch (Auth0Exception e) { future.completeExceptionally(e); return future; } + } - client.newCall(request).enqueue(new Callback() { - @Override - public void onFailure(@NotNull Call call, @NotNull IOException e) { - future.completeExceptionally(new Auth0Exception("Failed to execute request", e)); - } + private CompletableFuture> getResponseFuture(Auth0HttpResponse httpResponse) { + CompletableFuture> future = new CompletableFuture<>(); + try { + T body = parseResponseBody(httpResponse); + future = CompletableFuture.completedFuture(new ResponseImpl<>(httpResponse.getHeaders(), body, httpResponse.getCode())); + } catch (Auth0Exception e) { + future.completeExceptionally(e); + return future; + } + return future; + } - @Override - public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException { - try { - T parsedResponse = parseResponse(response); - future.complete(parsedResponse); - } catch (Auth0Exception e) { - future.completeExceptionally(e); - } - } - }); + /** + * Getter for the content-type header value to use on this request + * + * @return the content-type + */ + protected String getContentType() { + return CONTENT_TYPE_APPLICATION_JSON; + } - return future; + /** + * Responsible for parsing an unsuccessful request (status code other than 200) + * and generating a developer-friendly exception with the error details. + * + * @param response the unsuccessful response, as received. If its body is accessed, the buffer must be closed. + * @return the exception with the error details. + */ + protected Auth0Exception createResponseException(Auth0HttpResponse response) { + if (response.getCode() == STATUS_CODE_TOO_MANY_REQUEST) { + return createRateLimitException(response); + } + + String payload = response.getBody(); + MapType mapType = mapper.getTypeFactory().constructMapType(HashMap.class, String.class, Object.class); + try { + Map values = mapper.readValue(payload, mapType); + return new APIException(values, response.getCode()); + } catch (IOException e) { + return new APIException(payload, response.getCode(), e); + } + } + + private RateLimitException createRateLimitException(Auth0HttpResponse response) { + // -1 as default value if the header could not be found. + long limit = Long.parseLong(response.getHeader("x-ratelimit-limit", "-1")); + long remaining = Long.parseLong(response.getHeader("x-ratelimit-remaining", "-1")); + long reset = Long.parseLong(response.getHeader("x-ratelimit-reset", "-1")); + + TokenQuotaBucket clientQuotaLimit = HttpResponseHeadersUtils.getClientQuotaLimit(response.getHeaders()); + TokenQuotaBucket organizationQuotaLimit = HttpResponseHeadersUtils.getOrganizationQuotaLimit(response.getHeaders()); + + long retryAfter = Long.parseLong(response.getHeader("retry-after", "-1")); + + String payload = response.getBody(); + MapType mapType = mapper.getTypeFactory().constructMapType(HashMap.class, String.class, Object.class); + try { + Map values = mapper.readValue(payload, mapType); + + RateLimitException.Builder builder = new RateLimitException.Builder(limit, remaining, reset, values); + + builder.clientQuotaLimit(clientQuotaLimit); + builder.organizationQuotaLimit(organizationQuotaLimit); + builder.retryAfter(retryAfter); + + return builder.build(); + } catch (IOException e) { + RateLimitException.Builder builder = new RateLimitException.Builder(limit, remaining, reset); + builder.clientQuotaLimit(clientQuotaLimit); + builder.organizationQuotaLimit(organizationQuotaLimit); + builder.retryAfter(retryAfter); + return builder.build(); + } + } + + /** + * Adds an HTTP header to the request + * + * @param name the name of the header + * @param value the value of the header + * @return this same request instance + */ + public BaseRequest addHeader(String name, String value) { + headers.put(name, value); + return this; + } + + @Override + public BaseRequest addParameter(String name, Object value) { + parameters.put(name, value); + return this; + } + + @Override + public BaseRequest setBody(Object value) { + body = value; + return this; } } + diff --git a/src/main/java/com/auth0/net/CreateUserRequest.java b/src/main/java/com/auth0/net/CreateUserRequest.java deleted file mode 100644 index 7a59727f9..000000000 --- a/src/main/java/com/auth0/net/CreateUserRequest.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.auth0.net; - -import com.auth0.json.auth.CreatedUser; -import com.fasterxml.jackson.core.type.TypeReference; -import okhttp3.OkHttpClient; - -import java.util.Map; - -public class CreateUserRequest extends CustomRequest implements SignUpRequest { - - public CreateUserRequest(OkHttpClient client, String url) { - super(client, url, "POST", new TypeReference() { - }); - } - - @Override - public SignUpRequest setCustomFields(Map customFields) { - super.addParameter("user_metadata", customFields); - return this; - } -} diff --git a/src/main/java/com/auth0/net/CustomRequest.java b/src/main/java/com/auth0/net/CustomRequest.java deleted file mode 100644 index 45ad2af5a..000000000 --- a/src/main/java/com/auth0/net/CustomRequest.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.auth0.net; - -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; -import okhttp3.MediaType; -import okhttp3.OkHttpClient; -import okhttp3.RequestBody; -import okhttp3.ResponseBody; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -/** - * Request class that accepts parameters to be sent as part of its body. - * The content type of this request is "application/json". - *

- * This class is not thread-safe: - * It makes use of {@link HashMap} for storing the parameters. Make sure to not modify headers or the parameters - * from a different or un-synchronized thread. - * - * @param The type expected to be received as part of the response. - */ -public class CustomRequest extends ExtendedBaseRequest implements CustomizableRequest { - - private static final String CONTENT_TYPE_APPLICATION_JSON = "application/json"; - - private final ObjectMapper mapper; - private final TypeReference tType; - private final Map parameters; - private Object body; - - CustomRequest(OkHttpClient client, String url, String method, ObjectMapper mapper, TypeReference tType) { - super(client, url, method, mapper); - this.mapper = mapper; - this.tType = tType; - this.parameters = new HashMap<>(); - } - - public CustomRequest(OkHttpClient client, String url, String method, TypeReference tType) { - this(client, url, method, new ObjectMapper(), tType); - } - - @Override - @SuppressWarnings("deprecation") - protected RequestBody createRequestBody() throws IOException { - if (body == null && parameters.isEmpty()) { - return null; - } - byte[] jsonBody = mapper.writeValueAsBytes(body != null ? body : parameters); - // Use OkHttp v3 signature to ensure binary compatibility between v3 and v4 - // https://github.com/auth0/auth0-java/issues/324 - return RequestBody.create(MediaType.parse(CONTENT_TYPE_APPLICATION_JSON), jsonBody); - } - - @Override - protected T readResponseBody(ResponseBody body) throws IOException { - String payload = body.string(); - return mapper.readValue(payload, tType); - } - - @Override - public CustomRequest addHeader(String name, String value) { - //This is to avoid returning a different type - super.addHeader(name, value); - return this; - } - - @Override - public CustomRequest addParameter(String name, Object value) { - parameters.put(name, value); - return this; - } - - @Override - public CustomRequest setBody(Object value) { - body = value; - return this; - } -} diff --git a/src/main/java/com/auth0/net/CustomizableRequest.java b/src/main/java/com/auth0/net/CustomizableRequest.java deleted file mode 100644 index ecdc4fd70..000000000 --- a/src/main/java/com/auth0/net/CustomizableRequest.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.auth0.net; - -/** - * A request class that can be customized in different ways. - * i.e. setting headers, body parameters, etc. - * - * @param The type expected to be received as part of the response. - */ -@SuppressWarnings("UnusedReturnValue") -interface CustomizableRequest extends Request { - - /** - * Adds an HTTP header to the request - * - * @param name the name of the header - * @param value the value of the header - * @return this same request instance - */ - CustomizableRequest addHeader(String name, String value); - - /** - * Adds an body parameter to the request - * - * @param name the name of the parameter - * @param value the value of the parameter - * @return this same request instance - */ - CustomizableRequest addParameter(String name, Object value); - - /** - * Sets the response's body directly - * - * @param body the value to set as body - * @return this same request instance - */ - CustomizableRequest setBody(Object body); -} diff --git a/src/main/java/com/auth0/net/EmptyBodyRequest.java b/src/main/java/com/auth0/net/EmptyBodyRequest.java index 508414c80..a91a2d433 100644 --- a/src/main/java/com/auth0/net/EmptyBodyRequest.java +++ b/src/main/java/com/auth0/net/EmptyBodyRequest.java @@ -1,28 +1,29 @@ package com.auth0.net; +import com.auth0.client.mgmt.TokenProvider; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.HttpMethod; +import com.auth0.net.client.HttpRequestBody; import com.fasterxml.jackson.core.type.TypeReference; -import okhttp3.OkHttpClient; -import okhttp3.RequestBody; +import com.fasterxml.jackson.databind.ObjectMapper; /** * Request class that does not accept parameters to be sent as part of its body. * The content type of this request is "application/json". * * @param The type expected to be received as part of the response. - * @see CustomRequest + * @see BaseRequest */ -public class EmptyBodyRequest extends CustomRequest { +public class EmptyBodyRequest extends BaseRequest { - public EmptyBodyRequest(OkHttpClient client, String url, String method, TypeReference tType) { - super(client, url, method, tType); + public EmptyBodyRequest(Auth0HttpClient client, TokenProvider tokenProvider, String url, HttpMethod method, TypeReference tType) { + super(client, tokenProvider, url, method, tType); } @Override @SuppressWarnings("deprecation") - protected RequestBody createRequestBody() { - // Use OkHttp v3 signature to ensure binary compatibility between v3 and v4 - // https://github.com/auth0/auth0-java/issues/324 - return RequestBody.create(null, new byte[0]); + protected HttpRequestBody createRequestBody() { + return HttpRequestBody.create("application/json", new byte[0]); } @Override diff --git a/src/main/java/com/auth0/net/EmptyBodyVoidRequest.java b/src/main/java/com/auth0/net/EmptyBodyVoidRequest.java new file mode 100644 index 000000000..f93f8825c --- /dev/null +++ b/src/main/java/com/auth0/net/EmptyBodyVoidRequest.java @@ -0,0 +1,42 @@ +package com.auth0.net; + +import com.auth0.client.mgmt.TokenProvider; +import com.auth0.exception.Auth0Exception; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.Auth0HttpResponse; +import com.auth0.net.client.HttpMethod; +import com.auth0.net.client.HttpRequestBody; +import com.fasterxml.jackson.core.type.TypeReference; + +/** + * Request class that does not accept parameters to be sent as part of its body and request doesn't return any value on its success. + * The content type of this request is "application/json". + * + * @param The type expected to be received as part of the response. + * @see BaseRequest + */ +public class EmptyBodyVoidRequest extends BaseRequest { + public EmptyBodyVoidRequest(Auth0HttpClient client, TokenProvider tokenProvider, String url, HttpMethod method, TypeReference tType) { + super(client, tokenProvider, url, method, tType); + } + + @Override + @SuppressWarnings("deprecation") + protected HttpRequestBody createRequestBody() { + return HttpRequestBody.create("application/json", new byte[0]); + } + + @Override + public EmptyBodyVoidRequest addParameter(String name, Object value) { + //do nothing + return this; + } + @Override + protected T parseResponseBody(Auth0HttpResponse response) throws Auth0Exception { + if (!response.isSuccessful()) { + throw super.createResponseException(response); + } + return null; + } + +} diff --git a/src/main/java/com/auth0/net/ExtendedBaseRequest.java b/src/main/java/com/auth0/net/ExtendedBaseRequest.java deleted file mode 100644 index de60e1de3..000000000 --- a/src/main/java/com/auth0/net/ExtendedBaseRequest.java +++ /dev/null @@ -1,144 +0,0 @@ -package com.auth0.net; - -import com.auth0.exception.APIException; -import com.auth0.exception.Auth0Exception; -import com.auth0.exception.RateLimitException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.type.MapType; -import okhttp3.Request; -import okhttp3.*; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -/** - * A request class that is able to interact fluently with the Auth0 server. - * The default content type of this request is "application/json". - *

- * This class is not thread-safe: - * It makes use of {@link HashMap} for storing the parameters. Make sure to not modify headers or the parameters - * from a different or un-synchronized thread. - * //TODO: Merge with #BaseRequest on next major - * - * @param The type expected to be received as part of the response. - */ -abstract class ExtendedBaseRequest extends BaseRequest { - - private static final String CONTENT_TYPE_APPLICATION_JSON = "application/json"; - - private final String url; - private final String method; - private final ObjectMapper mapper; - private final Map headers; - - private static final int STATUS_CODE_TOO_MANY_REQUEST = 429; - - ExtendedBaseRequest(OkHttpClient client, String url, String method, ObjectMapper mapper) { - super(client); - this.url = url; - this.method = method; - this.mapper = mapper; - this.headers = new HashMap<>(); - } - - @Override - protected Request createRequest() throws Auth0Exception { - RequestBody body; - try { - body = this.createRequestBody(); - } catch (IOException e) { - throw new Auth0Exception("Couldn't create the request body.", e); - } - Request.Builder builder = new Request.Builder() - .url(url) - .method(method, body); - for (Map.Entry e : headers.entrySet()) { - builder.addHeader(e.getKey(), e.getValue()); - } - builder.addHeader("Content-Type", getContentType()); - return builder.build(); - } - - @Override - protected T parseResponse(Response response) throws Auth0Exception { - if (!response.isSuccessful()) { - throw createResponseException(response); - } - - try (ResponseBody body = response.body()) { - return readResponseBody(body); - } catch (IOException e) { - throw new APIException("Failed to parse the response body.", response.code(), e); - } - } - - /** - * Getter for the content-type header value to use on this request - * - * @return the content-type - */ - protected String getContentType() { - return CONTENT_TYPE_APPLICATION_JSON; - } - - /** - * Responsible for creating the payload that will be set as body on this request. - * - * @return the body to send as part of the request. - * @throws IOException if an error is raised during the creation of the body. - */ - protected abstract RequestBody createRequestBody() throws IOException; - - /** - * Responsible for parsing the payload that is received as part of the response. - * - * @param body the received body payload. The body buffer will automatically closed. - * @return the instance of type T, result of interpreting the payload. - * @throws IOException if an error is raised during the parsing of the body. - */ - protected abstract T readResponseBody(ResponseBody body) throws IOException; - - /** - * Adds an HTTP header to the request - * - * @param name the name of the header - * @param value the value of the header - * @return this same request instance - */ - public ExtendedBaseRequest addHeader(String name, String value) { - headers.put(name, value); - return this; - } - - /** - * Responsible for parsing an unsuccessful request (status code other than 200) - * and generating a developer-friendly exception with the error details. - * - * @param response the unsuccessful response, as received. If its body is accessed, the buffer must be closed. - * @return the exception with the error details. - */ - protected Auth0Exception createResponseException(Response response) { - if (response.code() == STATUS_CODE_TOO_MANY_REQUEST) { - return createRateLimitException(response); - } - - String payload = null; - try (ResponseBody body = response.body()) { - payload = body.string(); - MapType mapType = mapper.getTypeFactory().constructMapType(HashMap.class, String.class, Object.class); - Map values = mapper.readValue(payload, mapType); - return new APIException(values, response.code()); - } catch (IOException e) { - return new APIException(payload, response.code(), e); - } - } - - private RateLimitException createRateLimitException(Response response) { - // -1 as default value if the header could not be found. - long limit = Long.parseLong(response.header("X-RateLimit-Limit", "-1")); - long remaining = Long.parseLong(response.header("X-RateLimit-Remaining", "-1")); - long reset = Long.parseLong(response.header("X-RateLimit-Reset", "-1")); - return new RateLimitException(limit, remaining, reset); - } -} diff --git a/src/main/java/com/auth0/net/FormBodyRequest.java b/src/main/java/com/auth0/net/FormBodyRequest.java new file mode 100644 index 000000000..d44e43da4 --- /dev/null +++ b/src/main/java/com/auth0/net/FormBodyRequest.java @@ -0,0 +1,40 @@ +package com.auth0.net; + +import com.auth0.client.mgmt.TokenProvider; +import com.auth0.json.ObjectMapperProvider; +import com.auth0.json.auth.PushedAuthorizationResponse; +import com.auth0.net.client.*; +import com.auth0.utils.Asserts; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import okhttp3.FormBody; +import okhttp3.RequestBody; + +import java.io.IOException; + +/** + * Represents a form request. + * @param The type expected to be received as part of the response. + */ +public class FormBodyRequest extends BaseRequest { + + private static final String CONTENT_TYPE_FORM_DATA = "application/x-www-form-urlencoded"; + + FormBodyRequest(Auth0HttpClient client, TokenProvider tokenProvider, String url, HttpMethod method, ObjectMapper mapper, TypeReference tType) { + super(client, tokenProvider, url, method, mapper, tType); + } + + public FormBodyRequest(Auth0HttpClient client, TokenProvider tokenProvider, String url, HttpMethod method, TypeReference tType) { + this(client, tokenProvider, url, method, ObjectMapperProvider.getMapper(), tType); + } + + @Override + protected HttpRequestBody createRequestBody() throws IOException { + return HttpRequestBody.create(CONTENT_TYPE_FORM_DATA, new Auth0FormRequestBody(super.getParameters())); + } + + @Override + protected String getContentType() { + return CONTENT_TYPE_FORM_DATA; + } +} diff --git a/src/main/java/com/auth0/net/FormDataRequest.java b/src/main/java/com/auth0/net/FormDataRequest.java deleted file mode 100644 index 34de13730..000000000 --- a/src/main/java/com/auth0/net/FormDataRequest.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.auth0.net; - -import java.io.File; - -/** - * A request class that encodes its content as a form. - * i.e. for uploading attachments. - * - * @param The type expected to be received as part of the response. - */ -@SuppressWarnings("UnusedReturnValue") -interface FormDataRequest extends Request { - - /** - * Adds a key-value part to the form of this request - * - * @param name the name of the part - * @param value the value of the part - * @return this same request instance - */ - FormDataRequest addPart(String name, String value); - - /** - * Adds a file part to the form of this request - * - * @param name the name of the part - * @param file the file contents to send in this part - * @param mediaType the file contents media type - * @return this same request instance - */ - FormDataRequest addPart(String name, File file, String mediaType); -} diff --git a/src/main/java/com/auth0/net/MultipartRequest.java b/src/main/java/com/auth0/net/MultipartRequest.java index e296a5382..3261d58e9 100644 --- a/src/main/java/com/auth0/net/MultipartRequest.java +++ b/src/main/java/com/auth0/net/MultipartRequest.java @@ -1,8 +1,10 @@ package com.auth0.net; +import com.auth0.client.mgmt.TokenProvider; +import com.auth0.json.ObjectMapperProvider; +import com.auth0.net.client.*; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; -import okhttp3.*; import java.io.File; import java.io.IOException; @@ -19,30 +21,29 @@ * from a different or un-synchronized thread. * * @param The type expected to be received as part of the response. - * @see ExtendedBaseRequest + * @see BaseRequest */ -public class MultipartRequest extends ExtendedBaseRequest implements FormDataRequest { +public class MultipartRequest extends BaseRequest { private static final String CONTENT_TYPE_FORM_DATA = "multipart/form-data"; + private final Auth0MultipartRequestBody.Builder bodyBuilder; - private final MultipartBody.Builder bodyBuilder; private final TypeReference tType; private final ObjectMapper mapper; private int partsCount; - MultipartRequest(OkHttpClient client, String url, String method, ObjectMapper mapper, TypeReference tType, MultipartBody.Builder multipartBuilder) { - super(client, url, method, mapper); - if ("GET".equalsIgnoreCase(method)) { + MultipartRequest(Auth0HttpClient client, TokenProvider tokenProvider, String url, HttpMethod method, ObjectMapper mapper, TypeReference tType) { + super(client, tokenProvider, url, method, mapper, tType); + if (HttpMethod.GET.equals(method)) { throw new IllegalArgumentException("Multipart/form-data requests do not support the GET method."); } this.mapper = mapper; this.tType = tType; - this.bodyBuilder = multipartBuilder - .setType(MultipartBody.FORM); + this.bodyBuilder = Auth0MultipartRequestBody.newBuilder(); } - public MultipartRequest(OkHttpClient client, String url, String method, TypeReference tType) { - this(client, url, method, new ObjectMapper(), tType, new MultipartBody.Builder()); + public MultipartRequest(Auth0HttpClient client, TokenProvider tokenProvider, String url, HttpMethod method, TypeReference tType) { + this(client, tokenProvider, url, method, ObjectMapperProvider.getMapper(), tType); } @Override @@ -51,16 +52,16 @@ protected String getContentType() { } @Override - protected RequestBody createRequestBody() throws IOException { + protected HttpRequestBody createRequestBody() throws IOException { if (partsCount == 0) { throw new IOException("Cannot create multipart/form-data request body with zero parts."); } - return bodyBuilder.build(); + return HttpRequestBody.create("application/json", bodyBuilder.build()); } @Override - protected T readResponseBody(ResponseBody body) throws IOException { - String payload = body.string(); + protected T readResponseBody(Auth0HttpResponse response) throws IOException { + String payload = response.getBody(); return mapper.readValue(payload, tType); } @@ -71,7 +72,14 @@ public MultipartRequest addHeader(String name, String value) { return this; } - @Override + /** + * Adds a file part to the form of this request + * + * @param name the name of the part + * @param file the file contents to send in this part + * @param mediaType the file contents media type + * @return this same request instance + */ @SuppressWarnings("deprecation") public MultipartRequest addPart(String name, File file, String mediaType) { assertNotNull(name, "name"); @@ -79,19 +87,22 @@ public MultipartRequest addPart(String name, File file, String mediaType) { if (!file.exists()) { throw new IllegalArgumentException("Failed to add part because the file specified cannot be found."); } - // Use OkHttp v3 signature to ensure binary compatibility between v3 and v4 - // https://github.com/auth0/auth0-java/issues/324 - bodyBuilder.addFormDataPart(name, file.getName(), - RequestBody.create(MediaType.parse(mediaType), file)); + bodyBuilder.withFilePart(new Auth0MultipartRequestBody.FilePart(name, file, mediaType)); partsCount++; return this; } - @Override + /** + * Adds a key-value part to the form of this request + * + * @param name the name of the part + * @param value the value of the part + * @return this same request instance + */ public MultipartRequest addPart(String name, String value) { assertNotNull(name, "name"); assertNotNull(value, "value"); - bodyBuilder.addFormDataPart(name, value); + bodyBuilder.withPart(name, value); partsCount++; return this; } diff --git a/src/main/java/com/auth0/net/RateLimitInterceptor.java b/src/main/java/com/auth0/net/RateLimitInterceptor.java index c7b9d1ca1..842f143ad 100644 --- a/src/main/java/com/auth0/net/RateLimitInterceptor.java +++ b/src/main/java/com/auth0/net/RateLimitInterceptor.java @@ -1,7 +1,9 @@ package com.auth0.net; -import com.auth0.client.HttpOptions; +import com.auth0.exception.Auth0Exception; +import com.auth0.net.client.DefaultHttpClient; import net.jodah.failsafe.Failsafe; +import net.jodah.failsafe.FailsafeException; import net.jodah.failsafe.RetryPolicy; import net.jodah.failsafe.event.ExecutionAttemptedEvent; import net.jodah.failsafe.function.CheckedConsumer; @@ -16,11 +18,9 @@ * An OkHttp {@linkplain Interceptor} responsible for retrying rate-limit errors (429) using a configurable maximum * number of retries, and an exponential backoff on retry attempts. *

- * See {@link com.auth0.client.HttpOptions#setManagementAPIMaxRetries(int)} and {@link com.auth0.client.mgmt.ManagementAPI#ManagementAPI(String, String, HttpOptions)} - *

- *

* Note: This class is not intended for general use or extension, and may change at any time. *

+ * @see DefaultHttpClient */ public class RateLimitInterceptor implements Interceptor { @@ -59,24 +59,33 @@ public int getMaxRetries() { @NotNull @Override public Response intercept(@NotNull Chain chain) throws IOException { + if (maxRetries == 0) { + return chain.proceed(chain.request()); + } RetryPolicy retryPolicy = new RetryPolicy() .withMaxRetries(maxRetries) .withBackoff(INITIAL_INTERVAL, MAX_INTERVAL, ChronoUnit.MILLIS) .withJitter(JITTER) - .handleResultIf(response -> { - if (response.code() == 429) { - response.close(); - return true; - } - return false; - }); + .handleResultIf(response -> response.code() == 429); // For testing purposes only, allow test to hook into retry listener to enable verification of retry backoff if (retryListener != null) { retryPolicy.onRetry(retryListener); } - return Failsafe.with(retryPolicy).get(() -> chain.proceed(chain.request())); + try { + return Failsafe.with(retryPolicy).get((context) -> { + // ensure response of last recorded response prior to retry is closed + if (context.getLastResult() != null) { + context.getLastResult().close();; + } + return chain.proceed(chain.request()); + }); + } catch (FailsafeException fe) { + // throw Auth0Exception instead of FailSafe exception on error + // see https://github.com/auth0/auth0-java/issues/483 + throw new Auth0Exception("Failed to execute request", fe.getCause()); + } } } diff --git a/src/main/java/com/auth0/net/Request.java b/src/main/java/com/auth0/net/Request.java index a369d3db9..2b4e1491e 100644 --- a/src/main/java/com/auth0/net/Request.java +++ b/src/main/java/com/auth0/net/Request.java @@ -15,25 +15,42 @@ public interface Request { /** * Executes this request synchronously. * - * @return the response body JSON decoded as T + * @return a {@link Response} containing information about the response. * @throws APIException if the request was executed but the response wasn't successful. * @throws Auth0Exception if the request couldn't be created or executed successfully. */ - T execute() throws Auth0Exception; + Response execute() throws Auth0Exception; /** * Executes this request asynchronously. * - * Note: This method was added after the interface was released in version 1.0. - * It is defined as a default method for compatibility reasons. - * From version 2.0 on, the method will be abstract and all implementations of this interface - * will have to provide their own implementation. + * @return a {@linkplain CompletableFuture} representing the specified request. + */ + CompletableFuture> executeAsync(); + + /** + * Adds an HTTP header to the request + * + * @param name the name of the header + * @param value the value of the header + * @return this same request instance + */ + Request addHeader(String name, String value); + + /** + * Adds an body parameter to the request * - * The default implementation throws an {@linkplain UnsupportedOperationException}. + * @param name the name of the parameter + * @param value the value of the parameter + * @return this same request instance + */ + Request addParameter(String name, Object value); + + /** + * Sets the response's body directly * - * @return a {@linkplain CompletableFuture} representing the specified request. + * @param body the value to set as body + * @return this same request instance */ - default CompletableFuture executeAsync() { - throw new UnsupportedOperationException("executeAsync"); - } + Request setBody(Object body); } diff --git a/src/main/java/com/auth0/net/Response.java b/src/main/java/com/auth0/net/Response.java new file mode 100644 index 000000000..4064f1b9c --- /dev/null +++ b/src/main/java/com/auth0/net/Response.java @@ -0,0 +1,26 @@ +package com.auth0.net; + +import java.util.Map; + +/** + * Represents the response of an HTTP request executed by {@link Request}. + * + * @param the type of the parsed response body. + */ +public interface Response { + + /** + * @return the HTTP response headers. + */ + Map getHeaders(); + + /** + * @return the response body. + */ + T getBody(); + + /** + * @return the HTTP status code. + */ + int getStatusCode(); +} diff --git a/src/main/java/com/auth0/net/ResponseImpl.java b/src/main/java/com/auth0/net/ResponseImpl.java new file mode 100644 index 000000000..7cd35b996 --- /dev/null +++ b/src/main/java/com/auth0/net/ResponseImpl.java @@ -0,0 +1,32 @@ +package com.auth0.net; + +import java.util.Collections; +import java.util.Map; + +class ResponseImpl implements Response { + + private final Map headers; + private final T body; + private final int statusCode; + + ResponseImpl(Map headers, T body, int statusCode) { + this.headers = Collections.unmodifiableMap(headers); + this.body = body; + this.statusCode = statusCode; + } + + @Override + public Map getHeaders() { + return headers; + } + + @Override + public T getBody() { + return body; + } + + @Override + public int getStatusCode() { + return statusCode; + } +} diff --git a/src/main/java/com/auth0/net/SignUpRequest.java b/src/main/java/com/auth0/net/SignUpRequest.java index 0a4f56bc1..474f7c4a1 100644 --- a/src/main/java/com/auth0/net/SignUpRequest.java +++ b/src/main/java/com/auth0/net/SignUpRequest.java @@ -1,14 +1,21 @@ package com.auth0.net; import com.auth0.json.auth.CreatedUser; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.HttpMethod; +import com.fasterxml.jackson.core.type.TypeReference; import java.util.Map; /** * Class that represents a Create User call. */ -@SuppressWarnings("UnusedReturnValue") -public interface SignUpRequest extends Request { +public class SignUpRequest extends BaseRequest { + + public SignUpRequest(Auth0HttpClient client, String url) { + super(client, null, url, HttpMethod.POST, new TypeReference() { + }); + } /** * Setter for the additional fields to set when creating a user. @@ -16,5 +23,8 @@ public interface SignUpRequest extends Request { * @param customFields the list of custom fields. * @return this request instance. */ - SignUpRequest setCustomFields(Map customFields); + public SignUpRequest setCustomFields(Map customFields) { + super.addParameter("user_metadata", customFields); + return this; + } } diff --git a/src/main/java/com/auth0/net/Telemetry.java b/src/main/java/com/auth0/net/Telemetry.java index f439b024a..bf6c45ec2 100644 --- a/src/main/java/com/auth0/net/Telemetry.java +++ b/src/main/java/com/auth0/net/Telemetry.java @@ -1,7 +1,7 @@ package com.auth0.net; +import com.auth0.json.ObjectMapperProvider; import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; import java.util.Base64; import java.util.Collections; @@ -63,7 +63,7 @@ public Telemetry(String name, String version, String libraryVersion) { String tmpValue; try { - String json = new ObjectMapper().writeValueAsString(values); + String json = ObjectMapperProvider.getMapper().writeValueAsString(values); tmpValue = Base64.getUrlEncoder().encodeToString(json.getBytes()); } catch (JsonProcessingException e) { tmpValue = null; diff --git a/src/main/java/com/auth0/net/TokenQuotaBucket.java b/src/main/java/com/auth0/net/TokenQuotaBucket.java new file mode 100644 index 000000000..e6c192c21 --- /dev/null +++ b/src/main/java/com/auth0/net/TokenQuotaBucket.java @@ -0,0 +1,35 @@ +package com.auth0.net; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class TokenQuotaBucket { + private TokenQuotaLimit perHour; + private TokenQuotaLimit perDay; + + /** + * Constructor for TokenQuotaBucket. + */ + public TokenQuotaBucket(TokenQuotaLimit perHour, TokenQuotaLimit perDay) { + this.perHour = perHour; + this.perDay = perDay; + } + + /** + * @return the number of client credentials allowed per hour + */ + public TokenQuotaLimit getPerHour() { + return perHour; + } + + /** + * @return the number of client credentials allowed per hour + */ + public TokenQuotaLimit getPerDay() { + return perDay; + } + + +} diff --git a/src/main/java/com/auth0/net/TokenQuotaLimit.java b/src/main/java/com/auth0/net/TokenQuotaLimit.java new file mode 100644 index 000000000..966147ed3 --- /dev/null +++ b/src/main/java/com/auth0/net/TokenQuotaLimit.java @@ -0,0 +1,30 @@ +package com.auth0.net; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class TokenQuotaLimit { + private int quota; + private int remaining; + private int resetAfter; + + public TokenQuotaLimit(int quota, int remaining, int resetAfter) { + this.quota = quota; + this.remaining = remaining; + this.resetAfter = resetAfter; + } + + public int getQuota() { + return quota; + } + + public int getRemaining() { + return remaining; + } + + public int getResetAfter() { + return resetAfter; + } +} diff --git a/src/main/java/com/auth0/net/TokenRequest.java b/src/main/java/com/auth0/net/TokenRequest.java index 0b312fe26..8122d48f2 100644 --- a/src/main/java/com/auth0/net/TokenRequest.java +++ b/src/main/java/com/auth0/net/TokenRequest.java @@ -1,29 +1,48 @@ package com.auth0.net; import com.auth0.json.auth.TokenHolder; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.HttpMethod; import com.fasterxml.jackson.core.type.TypeReference; -import okhttp3.OkHttpClient; -public class TokenRequest extends CustomRequest implements AuthRequest { +/** + * Class that represents an OAuth 2.0 Authentication/Authorization request. The execution will return a {@link TokenHolder}. + */ +public class TokenRequest extends BaseRequest { - public TokenRequest(OkHttpClient client, String url) { - super(client, url, "POST", new TypeReference() { + public TokenRequest(Auth0HttpClient client, String url) { + super(client, null, url, HttpMethod.POST, new TypeReference() { }); } - @Override + /** + * Setter for the realm value to request + * + * @param realm the realm to request + * @return this request instance. + */ public TokenRequest setRealm(String realm) { super.addParameter("realm", realm); return this; } - @Override + /** + * Setter for the audience value to request + * + * @param audience the audience to request + * @return this request instance. + */ public TokenRequest setAudience(String audience) { super.addParameter("audience", audience); return this; } - @Override + /** + * Setter for the scope value to request + * + * @param scope the scope to request + * @return this request instance. + */ public TokenRequest setScope(String scope) { super.addParameter("scope", scope); return this; diff --git a/src/main/java/com/auth0/net/VoidRequest.java b/src/main/java/com/auth0/net/VoidRequest.java index a59840439..5538fe672 100644 --- a/src/main/java/com/auth0/net/VoidRequest.java +++ b/src/main/java/com/auth0/net/VoidRequest.java @@ -1,9 +1,11 @@ package com.auth0.net; +import com.auth0.client.mgmt.TokenProvider; import com.auth0.exception.Auth0Exception; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.Auth0HttpResponse; +import com.auth0.net.client.HttpMethod; import com.fasterxml.jackson.core.type.TypeReference; -import okhttp3.OkHttpClient; -import okhttp3.Response; import java.util.HashMap; @@ -14,21 +16,20 @@ * It makes use of {@link HashMap} for storing the parameters. Make sure to not modify headers or the parameters * from a different or un-synchronized thread. * - * @see CustomRequest + * @see BaseRequest */ -public class VoidRequest extends CustomRequest { +public class VoidRequest extends BaseRequest { - public VoidRequest(OkHttpClient client, String url, String method) { - super(client, url, method, new TypeReference() { + public VoidRequest(Auth0HttpClient client, TokenProvider tokenProvider, String url, HttpMethod method) { + super(client, tokenProvider, url, method, new TypeReference() { }); } @Override - protected Void parseResponse(Response response) throws Auth0Exception { + protected Void parseResponseBody(Auth0HttpResponse response) throws Auth0Exception { if (!response.isSuccessful()) { throw super.createResponseException(response); } - response.close(); return null; } } diff --git a/src/main/java/com/auth0/net/client/Auth0FormRequestBody.java b/src/main/java/com/auth0/net/client/Auth0FormRequestBody.java new file mode 100644 index 000000000..dc79469fe --- /dev/null +++ b/src/main/java/com/auth0/net/client/Auth0FormRequestBody.java @@ -0,0 +1,19 @@ +package com.auth0.net.client; + +import java.util.Map; + +/** + * Represents the body of a application/x-www-form-urlencoded request + */ +public class Auth0FormRequestBody { + + private final Map params; + + public Auth0FormRequestBody(Map params) { + this.params = params; + } + + public Map getParams() { + return params; + } +} diff --git a/src/main/java/com/auth0/net/client/Auth0HttpClient.java b/src/main/java/com/auth0/net/client/Auth0HttpClient.java new file mode 100644 index 000000000..1ebefa4c3 --- /dev/null +++ b/src/main/java/com/auth0/net/client/Auth0HttpClient.java @@ -0,0 +1,26 @@ +package com.auth0.net.client; + +import java.io.IOException; +import java.util.concurrent.CompletableFuture; + +/** + * The HttpClient interface defines how HTTP requests to the Auth0 APIs are made. + */ +public interface Auth0HttpClient { + + /** + * Builds, executes, and returns the result of a synchronous HTTP request to an Auth0 API. + * @param request the request to send. + * @return the response returned by the executed request. + * @throws IOException if the request can not be completed due to a network timeout or interruption. + */ + Auth0HttpResponse sendRequest(Auth0HttpRequest request) throws IOException; + + /** + * Builds and executes an asynchronous HTTP request to an Auth0 API. + * @param request the request to send. + * @return the {@link CompletableFuture} that represents the result of the asynchronous HTTP request. + */ + CompletableFuture sendRequestAsync(Auth0HttpRequest request); + +} diff --git a/src/main/java/com/auth0/net/client/Auth0HttpRequest.java b/src/main/java/com/auth0/net/client/Auth0HttpRequest.java new file mode 100644 index 000000000..1b7d83bf7 --- /dev/null +++ b/src/main/java/com/auth0/net/client/Auth0HttpRequest.java @@ -0,0 +1,68 @@ +package com.auth0.net.client; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +public class Auth0HttpRequest { + + private final String url; + private final Map headers; + private final HttpRequestBody body; + + private final HttpMethod method; + + public static Builder newBuilder(String url, HttpMethod method) { + return new Builder(url, method); + } + + private Auth0HttpRequest(Builder builder) { + this.url = builder.url; + this.method = builder.method; + this.body = builder.body; + this.headers = Objects.nonNull(builder.headers) ? new HashMap<>(builder.headers) : new HashMap<>(); + } + + public String getUrl() { + return url; + } + + public Map getHeaders() { + return headers; + } + + public HttpRequestBody getBody() { + return body; +} + + public HttpMethod getMethod() { + return method; + } + + public static class Builder { + private final String url; + private Map headers; + private HttpRequestBody body; + + private final HttpMethod method; + + private Builder(String url, HttpMethod method) { + this.url = url; + this.method = method; + } + + public Builder withHeaders(Map headers) { + this.headers = headers; + return this; + } + + public Builder withBody(HttpRequestBody body) { + this.body = body; + return this; + } + + public Auth0HttpRequest build() { + return new Auth0HttpRequest(this); + } + } +} diff --git a/src/main/java/com/auth0/net/client/Auth0HttpResponse.java b/src/main/java/com/auth0/net/client/Auth0HttpResponse.java new file mode 100644 index 000000000..28474bd96 --- /dev/null +++ b/src/main/java/com/auth0/net/client/Auth0HttpResponse.java @@ -0,0 +1,77 @@ +package com.auth0.net.client; + +import com.auth0.utils.Asserts; + +import java.util.HashMap; +import java.util.Map; + +public class Auth0HttpResponse { + + private final int code; + private final String body; + + private final Map headers; + + private Auth0HttpResponse(Builder builder) { + Asserts.assertNotNull(builder.code, "response code"); + Asserts.assertNotNull(builder.headers, "response headers"); + this.code = builder.code; + this.body = builder.body; + this.headers = new HashMap<>(builder.headers); + } + + public static Builder newBuilder() { + return new Builder(); + } + + public boolean isSuccessful() { + return code >= 200 && code <= 299; + } + + public String getBody() { + return body; + } + + public int getCode() { + return code; + } + + public Map getHeaders() { + return this.headers; + } + + public String getHeader(String header) { + return headers.get(header); + } + + public String getHeader(String header, String defaultValue) { + return headers.get(header) != null ? headers.get(header) : defaultValue; + } + public static class Builder { + private int code; + private String body; + + private Map headers = new HashMap<>(); + + private Builder() {} + + public Builder withStatusCode(int code) { + this.code = code; + return this; + } + + public Builder withBody(String body) { + this.body = body; + return this; + } + + public Builder withHeaders(Map headers) { + this.headers = headers; + return this; + } + + public Auth0HttpResponse build() { + return new Auth0HttpResponse(this); + } + } +} diff --git a/src/main/java/com/auth0/net/client/Auth0MultipartRequestBody.java b/src/main/java/com/auth0/net/client/Auth0MultipartRequestBody.java new file mode 100644 index 000000000..b0425b051 --- /dev/null +++ b/src/main/java/com/auth0/net/client/Auth0MultipartRequestBody.java @@ -0,0 +1,80 @@ +package com.auth0.net.client; + +import com.auth0.utils.Asserts; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; + +public class Auth0MultipartRequestBody { + + private final FilePart filePart; + private final Map parts; + + public static Builder newBuilder() { + return new Builder(); + } + + private Auth0MultipartRequestBody(Builder builder) { + this.filePart = builder.filePart; + this.parts = new HashMap<>(builder.parts); + } + + public FilePart getFilePart() { + return this.filePart; + } + + public Map getParts() { + return this.parts; + } + + static public class FilePart { + private final String partName; + private final File file; + private final String mediaType; + + public FilePart(String partName, File file, String mediaType) { + Asserts.assertNotNull(partName, "part name"); + Asserts.assertNotNull(file, "file"); + Asserts.assertNotNull(mediaType, "mediaType"); + + this.partName = partName; + this.file = file; + this.mediaType = mediaType; + } + + public String getPartName() { + return partName; + } + + public File getFile() { + return file; + } + + public String getMediaType() { + return mediaType; + } + + } + + public static class Builder { + FilePart filePart; + Map parts = new HashMap<>(); + + private Builder() {} + + public Builder withFilePart(FilePart filePart) { + this.filePart = filePart; + return this; + } + + public Builder withPart(String name, String value) { + parts.put(name, value); + return this; + } + + public Auth0MultipartRequestBody build() { + return new Auth0MultipartRequestBody(this); + } + } +} diff --git a/src/main/java/com/auth0/net/client/DefaultHttpClient.java b/src/main/java/com/auth0/net/client/DefaultHttpClient.java new file mode 100644 index 000000000..8daf3cea2 --- /dev/null +++ b/src/main/java/com/auth0/net/client/DefaultHttpClient.java @@ -0,0 +1,383 @@ +package com.auth0.net.client; + +import com.auth0.client.LoggingOptions; +import com.auth0.client.ProxyOptions; +import com.auth0.net.RateLimitInterceptor; +import com.auth0.net.TelemetryInterceptor; +import okhttp3.*; +import okhttp3.logging.HttpLoggingInterceptor; +import org.jetbrains.annotations.NotNull; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; + +/** + * Default implementation of {@link Auth0HttpClient} responsible for performing HTTP requests + * to the Auth0 APIs. Instances can be configured and created using the {@link Builder}. + *

+ * To minimize resource usage, instances should be created once and used in both the + * {@link com.auth0.client.mgmt.ManagementAPI} and {@link com.auth0.client.auth.AuthAPI} + * API clients. + *

+ *

+ * For most use cases, usage of this client is recommended. If you have more advanced use cases, + * such as the need to re-use an existing HTTP client, you may consider providing a custom + * implementation of {@link Auth0HttpClient}. + *

+ */ +public class DefaultHttpClient implements Auth0HttpClient { + + private final okhttp3.OkHttpClient client; + + public static DefaultHttpClient.Builder newBuilder() { + return new DefaultHttpClient.Builder(); + } + + /** + * For testing purposes only. + * @param client The client to inject for testing purposes. + */ + DefaultHttpClient(OkHttpClient client) { + this.client = client; + } + + /** + * For testing purposes only. + * @return the OkHttpClient + */ + OkHttpClient getOkClient() { + return this.client; + } + + private DefaultHttpClient(Builder builder) { + okhttp3.OkHttpClient.Builder clientBuilder = new okhttp3.OkHttpClient.Builder(); + clientBuilder.readTimeout(sanitizeTimeout(builder.readTimeout), TimeUnit.SECONDS); + clientBuilder.connectTimeout(sanitizeTimeout(builder.connectTimeout), TimeUnit.SECONDS); + clientBuilder.addInterceptor(getLoggingInterceptor(builder.loggingOptions)); + clientBuilder.addInterceptor(getTelemetryInterceptor(builder.telemetryEnabled)); + clientBuilder.addInterceptor(getRateLimitInterceptor(builder.maxRetries)); + clientBuilder.dispatcher(getDispatcher(builder.maxRequests, builder.maxRequestsPerHost)); + + configureProxy(clientBuilder, builder.proxyOptions); + this.client = clientBuilder.build(); + } + + /** + * Ensures that a timeout value is a number greater than zero. If not, zero will be returned. + * @param val the timeout value + * @return the timeout value if it is greater than zero; else zero is returned. + */ + private int sanitizeTimeout(int val) { + return Math.max(val, 0); + } + + @Override + public Auth0HttpResponse sendRequest(Auth0HttpRequest request) throws IOException { + Request okRequest = buildRequest(request); + try (Response response = client.newCall(okRequest).execute()) { + return buildResponse(response); + } + } + + @Override + public CompletableFuture sendRequestAsync(Auth0HttpRequest request) { + final CompletableFuture future = new CompletableFuture<>(); + Request okRequest = buildRequest(request); + + client.newCall(okRequest).enqueue(new Callback() { + @Override + public void onFailure(@NotNull Call call, @NotNull IOException e) { + future.completeExceptionally(e); + } + + @Override + public void onResponse(@NotNull Call call, @NotNull Response response) { + try { + future.complete(buildResponse(response)); + } catch (IOException e) { + future.completeExceptionally(e); + } finally { + response.close(); + } + } + }); + + return future; + } + + private Request buildRequest(Auth0HttpRequest a0Request) { + RequestBody okBody = addBody(a0Request); + + okhttp3.Request.Builder builder = new okhttp3.Request.Builder() + .url(a0Request.getUrl()) + .method(a0Request.getMethod().toString(), okBody); + for (Map.Entry e : a0Request.getHeaders().entrySet()) { + builder.addHeader(e.getKey(), e.getValue()); + } + + return builder.build(); + } + + /** + * Creates an {@link Auth0HttpResponse} from an OkHttp {@link Response}. + * + * @param okResponse the OkHttp response. + * @return the created Auth0HttpResponse + * @throws IOException if there is an issue reading the OkHttp response body. + */ + private Auth0HttpResponse buildResponse(Response okResponse) throws IOException { + Headers okHeaders = okResponse.headers(); + Map headers = new HashMap<>(); + + for (int i = 0; i < okHeaders.size(); i++) { + headers.put(okHeaders.name(i), okHeaders.value(i)); + } + + ResponseBody responseBody = okResponse.body(); + String content = null; + + if (Objects.nonNull(responseBody)) { + content = responseBody.string(); + } + return Auth0HttpResponse.newBuilder() + .withStatusCode(okResponse.code()) + .withBody(content) + .withHeaders(headers) + .build(); + } + + @SuppressWarnings("deprecation") + private RequestBody addBody(Auth0HttpRequest request) { + // null body added to request results in request without body + if (Objects.isNull(request.getBody()) || + HttpMethod.GET.equals(request.getMethod())) { + return null; + } + + HttpRequestBody body = request.getBody(); + RequestBody okBody; + + if (Objects.nonNull(body.getFormRequestBody())) { + Auth0FormRequestBody formData = body.getFormRequestBody(); + FormBody.Builder builder = new FormBody.Builder(); + for (Map.Entry entry : formData.getParams().entrySet()) { + Object val = entry.getValue(); + builder.add(entry.getKey(), val instanceof String ? (String) val : val.toString()); + } + okBody = builder.build(); + } + else if (Objects.nonNull(body.getMultipartRequestBody())) { + Auth0MultipartRequestBody multipartRequestBody = body.getMultipartRequestBody(); + MultipartBody.Builder bodyBuilder = new MultipartBody.Builder() + .setType(MultipartBody.FORM); + if (Objects.nonNull(multipartRequestBody.getFilePart())) { + bodyBuilder.addFormDataPart(multipartRequestBody.getFilePart().getPartName(), + multipartRequestBody.getFilePart().getFile().getName(), + RequestBody.create(MediaType.parse(multipartRequestBody.getFilePart().getMediaType()), multipartRequestBody.getFilePart().getFile())); + } + multipartRequestBody.getParts().forEach(bodyBuilder::addFormDataPart); + okBody = bodyBuilder.build(); + } else { + okBody = RequestBody.create(MediaType.parse(request.getBody().getContentType()), request.getBody().getContent()); + } + + return okBody; + } + + private HttpLoggingInterceptor getLoggingInterceptor(LoggingOptions loggingOptions) { + HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(); + if (Objects.isNull(loggingOptions)) { + loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.NONE); + return loggingInterceptor; + } + + switch (loggingOptions.getLogLevel()) { + case BASIC: + loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BASIC); + break; + case HEADERS: + loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.HEADERS); + break; + case BODY: + loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); + break; + case NONE: + default: + loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.NONE); + } + for (String header : loggingOptions.getHeadersToRedact()) { + loggingInterceptor.redactHeader(header); + } + return loggingInterceptor; + } + + private void configureProxy(okhttp3.OkHttpClient.Builder clientBuilder, ProxyOptions proxyOptions) { + if (Objects.nonNull(proxyOptions)) { + //Set proxy + clientBuilder.proxy(proxyOptions.getProxy()); + //Set authentication, if present + final String proxyAuth = proxyOptions.getBasicAuthentication(); + if (Objects.nonNull(proxyAuth)) { + clientBuilder.proxyAuthenticator(new Authenticator() { + + private static final String PROXY_AUTHORIZATION_HEADER = "Proxy-Authorization"; + + @Override + public okhttp3.Request authenticate(Route route, @NotNull Response response) { + if (Objects.nonNull(response.request().header(PROXY_AUTHORIZATION_HEADER))) { + return null; + } + return response.request().newBuilder() + .header(PROXY_AUTHORIZATION_HEADER, proxyAuth) + .build(); + } + }); + } + } + } + + private TelemetryInterceptor getTelemetryInterceptor(boolean telemetryEnabled) { + TelemetryInterceptor interceptor = new TelemetryInterceptor(); + interceptor.setEnabled(telemetryEnabled); + return interceptor; + } + + private RateLimitInterceptor getRateLimitInterceptor(int maxRetries) { + if (maxRetries < 0 || maxRetries > 10) { + throw new IllegalArgumentException("Retries must be between zero and ten."); + } + return new RateLimitInterceptor(maxRetries); + } + + private Dispatcher getDispatcher(int maxRequests, int maxRequestsPerHost) { + if (maxRequests < 1) { + throw new IllegalArgumentException("maxRequests must be one or greater."); + } + if (maxRequestsPerHost < 1) { + throw new IllegalArgumentException("maxRequestsPerHost must be one or greater."); + } + + Dispatcher dispatcher = new Dispatcher(); + dispatcher.setMaxRequests(maxRequests); + dispatcher.setMaxRequestsPerHost(maxRequestsPerHost); + return dispatcher; + } + + /** + * Builder for {@link DefaultHttpClient} instances. + */ + public static class Builder { + private int readTimeout = 10; + private int connectTimeout = 10; + private ProxyOptions proxyOptions; + private LoggingOptions loggingOptions; + private boolean telemetryEnabled = true; + private int maxRetries = 3; + private int maxRequests = 64; + private int maxRequestsPerHost = 5; + + /** + * Sets the value of the read timeout, in seconds. Defaults to ten seconds. A value of zero results in no read timeout. + * Negative numbers will be treated as zero. + * + * @param readTimeout the value of the read timeout to use. + * @return this builder instance. + */ + public Builder withReadTimeout(int readTimeout) { + this.readTimeout = readTimeout; + return this; + } + + /** + * Sets the value of the connect timeout, in seconds. Defaults to ten seconds. A value of zero results in no connect timeout. + * Negative numbers will be treated as zero. + * @param connectTimeout the value of the connect timeout to use. + * @return this builder instance. + */ + public Builder withConnectTimeout(int connectTimeout) { + this.connectTimeout = connectTimeout; + return this; + } + + /** + * Set the HTTP logging configuration options. If not set, no logs will be captured. + * @param loggingOptions the Logging configuration options. + * @return this builder instance. + */ + public Builder withLogging(LoggingOptions loggingOptions) { + this.loggingOptions = loggingOptions; + return this; + } + + /** + * Configure this client for use with a proxy. + * + * @param proxyOptions the Proxy configuration options + * @return this builder instance. + */ + public Builder withProxy(ProxyOptions proxyOptions) { + this.proxyOptions = proxyOptions; + return this; + } + + /** + * Configure this client to enable or disable sending telemetry data to Auth0 servers (on by default). + * @param telemetryEnabled true send telemetry data, false to not send. + * @return this builder instance. + */ + public Builder telemetryEnabled(boolean telemetryEnabled) { + this.telemetryEnabled = telemetryEnabled; + return this; + } + + /** + * Sets the maximum number of consecutive retries for API requests that fail due to rate-limits being reached. + * By default, rate-limited requests will be retried a maximum of three times. To disable retries on rate-limit + * errors, set this value to zero. + * + * @param maxRetries the maximum number of consecutive retries to attempt upon a rate-limit error. Defaults to three. + * Must be a number between zero (do not retry) and ten. + * + * @return this builder instance. + */ + public Builder withMaxRetries(int maxRetries) { + this.maxRetries = maxRetries; + return this; + } + + /** + * Sets the maximum number of requests to execute concurrently. + * + * @param maxRequests the number of requests to execute concurrently. Must be equal to or greater than one. + * @return this builder instance. + */ + public Builder withMaxRequests(int maxRequests) { + this.maxRequests = maxRequests; + return this; + } + + /** + * Sets the maximum number of requests for each host to execute concurrently. + * + * @param maxRequestsPerHost the maximum number of requests for each host to execute concurrently. Must be equal to or greater than one. + * @return this builder instance. + */ + public Builder withMaxRequestsPerHost(int maxRequestsPerHost) { + this.maxRequestsPerHost = maxRequestsPerHost; + return this; + } + + /** + * Create a {@code DefaultHttpClient} from this configured builder. + * @return the created {@code DefaultHttpClient}. + */ + public DefaultHttpClient build() { + return new DefaultHttpClient(this); + } + } + +} diff --git a/src/main/java/com/auth0/net/client/HttpMethod.java b/src/main/java/com/auth0/net/client/HttpMethod.java new file mode 100644 index 000000000..23752f00b --- /dev/null +++ b/src/main/java/com/auth0/net/client/HttpMethod.java @@ -0,0 +1,10 @@ +package com.auth0.net.client; + +/** + * Represents the HTTP methods when calling the Auth0 APIs. + */ +public enum HttpMethod { + + GET, POST, PUT, PATCH, DELETE; + +} diff --git a/src/main/java/com/auth0/net/client/HttpRequestBody.java b/src/main/java/com/auth0/net/client/HttpRequestBody.java new file mode 100644 index 000000000..de3dada8e --- /dev/null +++ b/src/main/java/com/auth0/net/client/HttpRequestBody.java @@ -0,0 +1,52 @@ +package com.auth0.net.client; + +public class HttpRequestBody { + + private byte[] content; + private String contentType; + private Auth0MultipartRequestBody multipartRequestBody; + private Auth0FormRequestBody formRequestBody; + + public static HttpRequestBody create(String contentType, byte[] content) { + return new HttpRequestBody(contentType, content); + } + + public static HttpRequestBody create(String contentType, Auth0MultipartRequestBody multipartRequestBody) { + return new HttpRequestBody(contentType, multipartRequestBody); + } + + public static HttpRequestBody create(String contentType, Auth0FormRequestBody formRequestBody) { + return new HttpRequestBody(contentType, formRequestBody); + } + + public byte[] getContent() { + return this.content; + } + + public Auth0MultipartRequestBody getMultipartRequestBody() { + return this.multipartRequestBody; + } + + public Auth0FormRequestBody getFormRequestBody() { + return this.formRequestBody; + } + + public String getContentType() { + return this.contentType; + } + + private HttpRequestBody(String contentType, byte[] content) { + this.contentType = contentType; + this.content = content; + } + + private HttpRequestBody(String contentType, Auth0MultipartRequestBody multipartRequestBody) { + this.contentType = contentType; + this.multipartRequestBody = multipartRequestBody; + } + + private HttpRequestBody(String contentType, Auth0FormRequestBody formRequestBody) { + this.contentType = contentType; + this.formRequestBody = formRequestBody; + } +} diff --git a/src/main/java/com/auth0/net/client/package-info.java b/src/main/java/com/auth0/net/client/package-info.java new file mode 100644 index 000000000..25884f076 --- /dev/null +++ b/src/main/java/com/auth0/net/client/package-info.java @@ -0,0 +1,5 @@ +/** + * Defines the HTTP client networking layer to make, execute, and parse HTTP + * responses to the Auth0 APIs. + */ +package com.auth0.net.client; diff --git a/src/main/java/com/auth0/utils/HttpResponseHeadersUtils.java b/src/main/java/com/auth0/utils/HttpResponseHeadersUtils.java new file mode 100644 index 000000000..12d4b14dc --- /dev/null +++ b/src/main/java/com/auth0/utils/HttpResponseHeadersUtils.java @@ -0,0 +1,82 @@ +package com.auth0.utils; + +import com.auth0.net.TokenQuotaLimit; +import com.auth0.net.TokenQuotaBucket; + +import java.util.Map; + +public class HttpResponseHeadersUtils { + + /** + * Gets the client token quota limits from the provided headers. + * + * @param headers the HTTP response headers. + * @return a TokenQuotaBucket containing client rate limits, or null if not present. + */ + public static TokenQuotaBucket getClientQuotaLimit(Map headers) { + String quotaHeader = headers.get("auth0-client-quota-limit"); + if (quotaHeader != null) { + return parseQuota(quotaHeader); + } + return null; + } + + /** + * Gets the organization token quota limits from the provided headers. + * + * @param headers the HTTP response headers. + * @return a TokenQuotaBucket containing organization rate limits, or null if not present. + */ + public static TokenQuotaBucket getOrganizationQuotaLimit(Map headers) { + String quotaHeader = headers.get("auth0-organization-quota-limit"); + if (quotaHeader != null) { + return parseQuota(quotaHeader); + } + return null; + } + + public static TokenQuotaBucket parseQuota(String tokenQuota) { + + TokenQuotaLimit perHour = null; + TokenQuotaLimit perDay = null; + + String[] parts = tokenQuota.split(","); + for (String part : parts) { + String[] attributes = part.split(";"); + int quota = 0, remaining = 0, time = 0; + + for (String attribute : attributes) { + String[] keyValue = attribute.split("="); + if (keyValue.length != 2) continue; + + String key = keyValue[0].trim(); + String value = keyValue[1].trim(); + + switch (key) { + case "q": + quota = Integer.parseInt(value); + break; + case "r": + remaining = Integer.parseInt(value); + break; + case "t": + time = Integer.parseInt(value); + break; + } + } + + if (attributes.length >0 && attributes[0].contains("per_hour")) { + perHour = new TokenQuotaLimit(quota, remaining, time); + } else if (attributes.length >0 && attributes[0].contains("per_day")) { + perDay = new TokenQuotaLimit(quota, remaining, time); + } + } + + if(perHour == null && perDay == null) { + return null; + } + + return new TokenQuotaBucket(perHour, perDay); + } + +} diff --git a/src/main/java/com/auth0/utils/tokens/IdTokenVerifier.java b/src/main/java/com/auth0/utils/tokens/IdTokenVerifier.java index 808cb220f..9a354713a 100644 --- a/src/main/java/com/auth0/utils/tokens/IdTokenVerifier.java +++ b/src/main/java/com/auth0/utils/tokens/IdTokenVerifier.java @@ -138,14 +138,26 @@ public void verify(String token, String nonce, Integer maxAuthenticationAge) thr // Org verification if (this.organization != null) { - String orgClaim = decoded.getClaim("org_id").asString(); - if (isEmpty(orgClaim)) { - throw new IdTokenValidationException("Organization Id (org_id) claim must be a string present in the ID token"); + String org = this.organization.trim(); + if (org.startsWith("org_")) { + // org ID + String orgClaim = decoded.getClaim("org_id").asString(); + if (isEmpty(orgClaim)) { + throw new IdTokenValidationException("Organization Id (org_id) claim must be a string present in the ID token"); + } + if (!this.organization.equals(orgClaim)) { + throw new IdTokenValidationException(String.format("Organization (org_id) claim mismatch in the ID token; expected \"%s\" but found \"%s\"", this.organization, orgClaim)); + } + } else { + // org name + String orgNameClaim = decoded.getClaim("org_name").asString(); + if (isEmpty(orgNameClaim)) { + throw new IdTokenValidationException("Organization name (org_name) claim must be a string present in the ID token"); + } + if (!org.toLowerCase().equals(orgNameClaim)) { + throw new IdTokenValidationException(String.format("Organization (org_name) claim mismatch in the ID token; expected \"%s\" but found \"%s\"", this.organization, orgNameClaim)); + } } - if (!this.organization.equals(orgClaim)) { - throw new IdTokenValidationException(String.format("Organization (org_id) claim mismatch in the ID token; expected \"%s\" but found \"%s\"", this.organization, orgClaim)); - } - } final Calendar cal = Calendar.getInstance(); diff --git a/src/test/java/com/auth0/AssertsUtil.java b/src/test/java/com/auth0/AssertsUtil.java new file mode 100644 index 000000000..822851e7f --- /dev/null +++ b/src/test/java/com/auth0/AssertsUtil.java @@ -0,0 +1,20 @@ +package com.auth0; + +import org.junit.jupiter.api.function.Executable; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class AssertsUtil { + + public static T verifyThrows(Class expectedType, Executable executable) { + return assertThrows(expectedType, executable); + } + + public static T verifyThrows(Class expectedType, Executable executable, String message) { + T result = assertThrows(expectedType, executable); + assertThat(result.getMessage(), is(message)); + return result; + } +} diff --git a/src/test/java/com/auth0/client/HttpOptionsTest.java b/src/test/java/com/auth0/client/HttpOptionsTest.java new file mode 100644 index 000000000..a3d74f5bf --- /dev/null +++ b/src/test/java/com/auth0/client/HttpOptionsTest.java @@ -0,0 +1,80 @@ +package com.auth0.client; + +import org.junit.jupiter.api.Test; + +import static com.auth0.AssertsUtil.verifyThrows; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +@SuppressWarnings("deprecation") +public class HttpOptionsTest { + + @Test + public void setsOptions() { + HttpOptions opts = new HttpOptions(); + opts.setLoggingOptions(new LoggingOptions(LoggingOptions.LogLevel.NONE)); + opts.setConnectTimeout(20); + opts.setReadTimeout(30); + opts.setMaxRequests(5); + opts.setMaxRequestsPerHost(3); + opts.setManagementAPIMaxRetries(5); + + assertThat(opts.getLoggingOptions().getLogLevel(), is(LoggingOptions.LogLevel.NONE)); + assertThat(opts.getConnectTimeout(), is(20)); + assertThat(opts.getReadTimeout(), is(30)); + assertThat(opts.getMaxRequests(), is(5)); + assertThat(opts.getManagementAPIMaxRetries(), is(5)); + assertThat(opts.getMaxRequestsPerHost(), is(3)); + } + + @Test + public void connectTimeoutMustNotBeNegative() { + HttpOptions opts = new HttpOptions(); + opts.setConnectTimeout(-1); + assertThat(opts.getConnectTimeout(), is(0)); + } + + @Test + public void readTimeoutMustNotBeNegative() { + HttpOptions opts = new HttpOptions(); + opts.setReadTimeout(-1); + assertThat(opts.getReadTimeout(), is(0)); + } + + @Test + public void apiMaxRetriesNotLessThan0() { + HttpOptions opts = new HttpOptions(); + verifyThrows(IllegalArgumentException.class, + () -> opts.setManagementAPIMaxRetries(-1), + "Retries must be between zero and ten."); + } + + @Test + public void apiMaxRetriesNotGreaterThan10() { + HttpOptions opts = new HttpOptions(); + verifyThrows(IllegalArgumentException.class, + () -> opts.setManagementAPIMaxRetries(11), + "Retries must be between zero and ten."); + } + + @Test + public void maxRequestsMustBePositive() { + HttpOptions opts = new HttpOptions(); + verifyThrows(IllegalArgumentException.class, () -> opts.setMaxRequests(0), "maxRequests must be one or greater."); + } + + @Test + public void maxRequestsPerHostMustBePositive() { + HttpOptions opts = new HttpOptions(); + } + + @Test + public void usesDefaults() { + HttpOptions opts = new HttpOptions(); + assertThat(opts.getReadTimeout(), is(10)); + assertThat(opts.getConnectTimeout(), is(10)); + assertThat(opts.getMaxRequests(), is(64)); + assertThat(opts.getMaxRequestsPerHost(), is(5)); + assertThat(opts.getManagementAPIMaxRetries(), is(3)); + } +} diff --git a/src/test/java/com/auth0/client/MockServer.java b/src/test/java/com/auth0/client/MockServer.java index f55be0a29..7dbe2217e 100644 --- a/src/test/java/com/auth0/client/MockServer.java +++ b/src/test/java/com/auth0/client/MockServer.java @@ -1,5 +1,6 @@ package com.auth0.client; +import com.auth0.net.TokenQuotaBucket; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.type.CollectionType; import com.fasterxml.jackson.databind.type.MapType; @@ -28,6 +29,10 @@ public class MockServer { public static final String AUTH_ERROR_WITH_DESCRIPTION = "src/test/resources/auth/error_with_description.json"; public static final String AUTH_ERROR_WITH_DESCRIPTION_AND_EXTRA_PROPERTIES = "src/test/resources/auth/error_with_description_and_extra_properties.json"; public static final String AUTH_ERROR_PLAINTEXT = "src/test/resources/auth/error_plaintext.json"; + public static final String AUTH_OOB_AUTHENTICATOR_RESPONSE = "src/test/resources/auth/add_oob_authenticator_response.json"; + public static final String AUTH_OTP_AUTHENTICATOR_RESPONSE = "src/test/resources/auth/add_otp_authenticator_response.json"; + public static final String AUTH_LIST_AUTHENTICATORS_RESPONSE = "src/test/resources/auth/list_authenticators_response.json"; + public static final String AUTH_CHALLENGE_RESPONSE = "src/test/resources/auth/mfa_challenge_request_response.json"; public static final String MGMT_ERROR_WITH_MESSAGE = "src/test/resources/mgmt/error_with_message.json"; public static final String MGMT_CLIENT_GRANTS_LIST = "src/test/resources/mgmt/client_grants_list.json"; public static final String MGMT_CLIENT_GRANTS_PAGED_LIST = "src/test/resources/mgmt/client_grants_paged_list.json"; @@ -35,9 +40,18 @@ public class MockServer { public static final String MGMT_CLIENTS_LIST = "src/test/resources/mgmt/clients_list.json"; public static final String MGMT_CLIENTS_PAGED_LIST = "src/test/resources/mgmt/clients_paged_list.json"; public static final String MGMT_CLIENT = "src/test/resources/mgmt/client.json"; + public static final String MGMT_CLIENT_CREDENTIAL = "src/test/resources/mgmt/client_credential.json"; + public static final String MGMT_CLIENT_CREDENTIAL_LIST = "src/test/resources/mgmt/client_credential_list.json"; public static final String MGMT_CONNECTIONS_LIST = "src/test/resources/mgmt/connections_list.json"; public static final String MGMT_CONNECTIONS_PAGED_LIST = "src/test/resources/mgmt/connections_paged_list.json"; public static final String MGMT_CONNECTION = "src/test/resources/mgmt/connection.json"; + public static final String MGMT_CONNECTION_SCIM_CONFIGURATION = "src/test/resources/mgmt/connection_scim_configuration.json"; + public static final String MGMT_CONNECTION_DEFAULT_SCIM_CONFIGURATION = "src/test/resources/mgmt/default_connection_scim_configuration.json"; + public static final String MGMT_CONNECTION_SCIM_TOKENS = "src/test/resources/mgmt/connection_scim_tokens.json"; + public static final String MGMT_CONNECTION_SCIM_TOKEN = "src/test/resources/mgmt/connection_scim_token.json"; + public static final String MGMT_ENABLED_CLIENTS_FOR_CONNECTION = "src/test/resources/mgmt/enabled_clients_for_connection.json"; + public static final String MGMT_CONNECTION_KEY = "src/test/resources/mgmt/connection_key.json"; + public static final String MGMT_ROTATE_KEY = "src/test/resources/mgmt/rotate_key.json"; public static final String MGMT_DEVICE_CREDENTIALS_LIST = "src/test/resources/mgmt/device_credentials_list.json"; public static final String MGMT_DEVICE_CREDENTIALS = "src/test/resources/mgmt/device_credentials.json"; public static final String MGMT_GRANTS_LIST = "src/test/resources/mgmt/grants_list.json"; @@ -72,9 +86,16 @@ public class MockServer { public static final String MGMT_USERS_PAGED_LIST = "src/test/resources/mgmt/users_paged_list.json"; public static final String MGMT_USER_PERMISSIONS_PAGED_LIST = "src/test/resources/mgmt/user_permissions_paged_list.json"; public static final String MGMT_USER_ROLES_PAGED_LIST = "src/test/resources/mgmt/user_roles_paged_list.json"; + public static final String MGMT_REFRESH_TOKEN = "src/test/resources/mgmt/refresh_token.json"; + public static final String MGMT_SESSION = "src/test/resources/mgmt/session.json"; + public static final String MGMT_USER_REFRESH_TOKENS = "src/test/resources/mgmt/user_refresh_tokens.json"; + public static final String MGMT_USER_SESSIONS = "src/test/resources/mgmt/user_sessions.json"; public static final String MGMT_USER = "src/test/resources/mgmt/user.json"; public static final String MGMT_RECOVERY_CODE = "src/test/resources/mgmt/recovery_code.json"; public static final String MGMT_IDENTITIES_LIST = "src/test/resources/mgmt/identities_list.json"; + public static final String MGMT_PROMPT = "src/test/resources/mgmt/prompt.json"; + public static final String MGMT_CUSTOM_TEXT_PROMPT = "src/test/resources/mgmt/custom_text_prompt.json"; + public static final String MGMT_PARTIALS_PROMPT = "src/test/resources/mgmt/partials_prompt.json"; public static final String MGMT_GUARDIAN_AUTHENTICATION_POLICIES_LIST = "src/test/resources/mgmt/guardian_authentication_policies_list.json"; public static final String MGMT_GUARDIAN_ENROLLMENT = "src/test/resources/mgmt/guardian_enrollment.json"; public static final String MGMT_GUARDIAN_ENROLLMENTS_LIST = "src/test/resources/mgmt/guardian_enrollments_list.json"; @@ -99,9 +120,24 @@ public class MockServer { public static final String MGMT_JOB_POST_USERS_IMPORTS = "src/test/resources/mgmt/job_post_users_imports.json"; public static final String MGMT_JOB_POST_USERS_IMPORTS_INPUT = "src/test/resources/mgmt/job_post_users_imports_input.json"; public static final String MGMT_JOB_ERROR_DETAILS = "src/test/resources/mgmt/job_error_details.json"; + public static final String MGMT_NETWORK_ACLS_LIST = "src/test/resources/mgmt/network_acls_list.json"; + public static final String MGMT_NETWORK_ACLS = "src/test/resources/mgmt/network_acls.json"; + public static final String MGMT_USER_ATTRIBUTE_PROFILES_LIST = "src/test/resources/mgmt/user_attribute_profiles_list.json"; + public static final String MGMT_USER_ATTRIBUTE_PROFILE = "src/test/resources/mgmt/user_attribute_profile.json"; + public static final String MGMT_USER_ATTRIBUTE_PROFILE_TEMPLATE = "src/test/resources/mgmt/user_attribute_profile_template.json"; + public static final String MGMT_USER_ATTRIBUTE_PROFILE_TEMPLATES_LIST = "src/test/resources/mgmt/user_attribute_profile_templates_list.json"; public static final String MULTIPART_SAMPLE = "src/test/resources/mgmt/multipart_sample.json"; public static final String PASSWORDLESS_EMAIL_RESPONSE = "src/test/resources/auth/passwordless_email.json"; public static final String PASSWORDLESS_SMS_RESPONSE = "src/test/resources/auth/passwordless_sms.json"; + public static final String PUSHED_AUTHORIZATION_RESPONSE = "src/test/resources/auth/pushed_authorization_response.json"; + public static final String BACK_CHANNEL_AUTHORIZE_RESPONSE = "src/test/resources/auth/back_channel_authorize_response.json"; + public static final String BACK_CHANNEL_LOGIN_STATUS_RESPONSE = "src/test/resources/auth/back_channel_login_status_response.json"; + public static final String AUTHENTICATOR_METHOD_BY_ID = "src/test/resources/mgmt/authenticator_method_by_id.json"; + public static final String AUTHENTICATOR_METHOD_CREATE = "src/test/resources/mgmt/authenticator_method_create.json"; + public static final String AUTHENTICATOR_METHOD_LIST = "src/test/resources/mgmt/authenticator_method_list.json"; + public static final String AUTHENTICATOR_METHOD_PAGED_LIST = "src/test/resources/mgmt/authenticator_method_paged_list.json"; + public static final String AUTHENTICATOR_METHOD_UPDATE = "src/test/resources/mgmt/authenticator_method_update.json"; + public static final String AUTHENTICATOR_METHOD_UPDATE_BY_ID = "src/test/resources/mgmt/authenticator_method_update_by_id.json"; public static final String ORGANIZATION = "src/test/resources/mgmt/organization.json"; public static final String ORGANIZATIONS_LIST = "src/test/resources/mgmt/organizations_list.json"; public static final String ORGANIZATIONS_PAGED_LIST = "src/test/resources/mgmt/organizations_paged_list.json"; @@ -114,6 +150,9 @@ public class MockServer { public static final String ORGANIZATION_CONNECTION = "src/test/resources/mgmt/organization_connection.json"; public static final String ORGANIZATION_MEMBER_ROLES_LIST = "src/test/resources/mgmt/organization_member_roles_list.json"; public static final String ORGANIZATION_MEMBER_ROLES_PAGED_LIST = "src/test/resources/mgmt/organization_member_roles_paged_list.json"; + public static final String ORGANIZATION_CLIENT_GRANTS = "src/test/resources/mgmt/organization_client_grants.json"; + public static final String ORGANIZATION_CLIENT_GRANTS_PAGED_LIST = "src/test/resources/mgmt/organization_client_grants_paged_list.json"; + public static final String ORGANIZATION_CLIENT_GRANT = "src/test/resources/mgmt/organization_client_grant.json"; public static final String INVITATION = "src/test/resources/mgmt/invitation.json"; public static final String INVITATIONS_LIST = "src/test/resources/mgmt/invitations_list.json"; public static final String INVITATIONS_PAGED_LIST = "src/test/resources/mgmt/invitations_paged_list.json"; @@ -131,6 +170,13 @@ public class MockServer { public static final String KEY_LIST = "src/test/resources/mgmt/key_list.json"; public static final String KEY_REVOKE = "src/test/resources/mgmt/key_revoke.json"; public static final String KEY_ROTATE = "src/test/resources/mgmt/key_rotate.json"; + public static final String ENCRYPTION_KEY = "src/test/resources/mgmt/encryption_key.json"; + public static final String ENCRYPTION_KEYS_LIST = "src/test/resources/mgmt/encryption_keys_list.json"; + public static final String RATE_LIMIT_ERROR = "src/test/resources/mgmt/rate_limit_error.json"; + public static final String SELF_SERVICE_PROFILES_LIST = "src/test/resources/mgmt/self_service_profiles_list.json"; + public static final String SELF_SERVICE_PROFILE_RESPONSE = "src/test/resources/mgmt/self_service_profile_response.json"; + public static final String SELF_SERVICE_PROFILE_CUSTOM_TEXT = "src/test/resources/mgmt/self_service_profile_custom_text.json"; + public static final String SELF_SERVICE_PROFILE_SSO_TICKET = "src/test/resources/mgmt/self_service_profile_sso_ticket.json"; private final MockWebServer server; @@ -165,22 +211,65 @@ public void jsonResponse(String path, int statusCode) throws IOException { public void noContentResponse() { MockResponse response = new MockResponse() - .setResponseCode(204) - .addHeader("Content-Type", "application/json") - .setBody(""); + .setResponseCode(204) + .addHeader("Content-Type", "application/json") + .setBody(""); + server.enqueue(response); + } + + public void rateLimitReachedResponse(long limit, long remaining, long reset) throws IOException { + rateLimitReachedResponse(limit, remaining, reset, null); + } + + public void rateLimitReachedResponse(long limit, long remaining, long reset, String path) throws IOException { + MockResponse response = new MockResponse().setResponseCode(429); + if (limit != -1) { + response.addHeader("x-ratelimit-limit", String.valueOf(limit)); + } + if (remaining != -1) { + response.addHeader("x-ratelimit-remaining", String.valueOf(remaining)); + } + if (reset != -1) { + response.addHeader("x-ratelimit-reset", String.valueOf(reset)); + } + if (path != null) { + response + .addHeader("Content-Type", "application/json") + .setBody(readTextFile(path)); + } server.enqueue(response); } - public void rateLimitReachedResponse(long limit, long remaining, long reset) { + public void rateLimitReachedResponse(long limit, long remaining, long reset, + String clientQuotaLimit, String organizationQuotaLimit, long retryAfter) throws IOException { + rateLimitReachedResponse(limit, remaining, reset, null, clientQuotaLimit, organizationQuotaLimit, retryAfter); + } + + public void rateLimitReachedResponse(long limit, long remaining, long reset, String path, String clientQuotaLimit, + String organizationQuotaLimit, long retryAfter) throws IOException { MockResponse response = new MockResponse().setResponseCode(429); if (limit != -1) { - response.addHeader("X-RateLimit-Limit", String.valueOf(limit)); + response.addHeader("x-ratelimit-limit", String.valueOf(limit)); } if (remaining != -1) { - response.addHeader("X-RateLimit-Remaining", String.valueOf(remaining)); + response.addHeader("x-ratelimit-remaining", String.valueOf(remaining)); } if (reset != -1) { - response.addHeader("X-RateLimit-Reset", String.valueOf(reset)); + response.addHeader("x-ratelimit-reset", String.valueOf(reset)); + } + if (clientQuotaLimit != null) { + response.addHeader("auth0-client-quota-limit", clientQuotaLimit); + } + if (organizationQuotaLimit != null) { + response.addHeader("auth0-organization-quota-limit", organizationQuotaLimit); + } + if (retryAfter != -1) { + response.addHeader("retry-after", String.valueOf(retryAfter)); + } + if (path != null) { + response + .addHeader("Content-Type", "application/json") + .setBody(readTextFile(path)); } server.enqueue(response); } diff --git a/src/test/java/com/auth0/client/RecordedRequestMatcher.java b/src/test/java/com/auth0/client/RecordedRequestMatcher.java index a825729b6..f0e659878 100644 --- a/src/test/java/com/auth0/client/RecordedRequestMatcher.java +++ b/src/test/java/com/auth0/client/RecordedRequestMatcher.java @@ -1,5 +1,6 @@ package com.auth0.client; +import com.auth0.net.client.HttpMethod; import okhttp3.HttpUrl; import okhttp3.mockwebserver.RecordedRequest; import org.hamcrest.Description; @@ -136,8 +137,8 @@ public void describeTo(Description description) { } } - public static RecordedRequestMatcher hasMethodAndPath(String method, String path) { - return new RecordedRequestMatcher(method, path, METHOD_PATH); + public static RecordedRequestMatcher hasMethodAndPath(HttpMethod method, String path) { + return new RecordedRequestMatcher(method.toString(), path, METHOD_PATH); } public static RecordedRequestMatcher hasHeader(String name, String value) { diff --git a/src/test/java/com/auth0/client/auth/AuthAPITest.java b/src/test/java/com/auth0/client/auth/AuthAPITest.java index 9447f2d03..b65c51ad1 100644 --- a/src/test/java/com/auth0/client/auth/AuthAPITest.java +++ b/src/test/java/com/auth0/client/auth/AuthAPITest.java @@ -1,30 +1,33 @@ package com.auth0.client.auth; -import com.auth0.client.HttpOptions; -import com.auth0.client.LoggingOptions; import com.auth0.client.MockServer; -import com.auth0.client.ProxyOptions; import com.auth0.exception.APIException; +import com.auth0.json.ObjectMapperProvider; import com.auth0.json.auth.*; +import com.auth0.net.BaseRequest; import com.auth0.net.Request; -import com.auth0.net.*; +import com.auth0.net.SignUpRequest; +import com.auth0.net.TokenRequest; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.Auth0HttpRequest; +import com.auth0.net.client.Auth0HttpResponse; +import com.auth0.net.client.HttpMethod; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; -import okhttp3.*; -import okhttp3.logging.HttpLoggingInterceptor; -import okhttp3.logging.HttpLoggingInterceptor.Level; import okhttp3.mockwebserver.RecordedRequest; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.mockito.Mockito; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import java.io.FileReader; -import java.net.Proxy; +import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.stream.Collectors; +import static com.auth0.AssertsUtil.verifyThrows; import static com.auth0.client.MockServer.*; import static com.auth0.client.RecordedRequestMatcher.hasHeader; import static com.auth0.client.RecordedRequestMatcher.hasMethodAndPath; @@ -34,6 +37,8 @@ import static org.hamcrest.Matchers.*; import static org.hamcrest.collection.IsMapContaining.hasEntry; import static org.hamcrest.collection.IsMapContaining.hasKey; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; public class AuthAPITest { @@ -45,447 +50,117 @@ public class AuthAPITest { private MockServer server; private AuthAPI api; + private AuthAPI apiNoClientAuthentication; - @SuppressWarnings("deprecation") - @Rule - public ExpectedException exception = ExpectedException.none(); - - @Before + @BeforeEach public void setUp() throws Exception { server = new MockServer(); - api = new AuthAPI(server.getBaseUrl(), CLIENT_ID, CLIENT_SECRET); + api = AuthAPI.newBuilder(server.getBaseUrl(), CLIENT_ID, CLIENT_SECRET).build(); + apiNoClientAuthentication = AuthAPI.newBuilder(server.getBaseUrl(), CLIENT_ID).build(); } - @After + @AfterEach public void tearDown() throws Exception { server.stop(); } // Configuration - @Test - public void shouldAcceptDomainWithNoScheme() { - AuthAPI api = new AuthAPI("me.something.com", CLIENT_ID, CLIENT_SECRET); - - assertThat(api.getBaseUrl(), is(notNullValue())); - assertThat(api.getBaseUrl().toString(), isUrl("https", "me.something.com")); - } - - @Test - public void shouldAcceptDomainWithHttpScheme() { - AuthAPI api = new AuthAPI("http://me.something.com", CLIENT_ID, CLIENT_SECRET); - - assertThat(api.getBaseUrl(), is(notNullValue())); - assertThat(api.getBaseUrl().toString(), isUrl("http", "me.something.com")); - } - - @Test - public void shouldThrowWhenDomainIsInvalid() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("The domain had an invalid format and couldn't be parsed as an URL."); - new AuthAPI("", CLIENT_ID, CLIENT_SECRET); - } - - @Test - public void shouldThrowWhenDomainIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'domain' cannot be null!"); - new AuthAPI(null, CLIENT_ID, CLIENT_SECRET); - } - - @Test - public void shouldThrowWhenClientIdIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'client id' cannot be null!"); - new AuthAPI(DOMAIN, null, CLIENT_SECRET); - } - - @Test - public void shouldThrowWhenClientSecretIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'client secret' cannot be null!"); - new AuthAPI(DOMAIN, CLIENT_ID, null); - } - - @Test - public void shouldUseDefaultTimeValues() { - AuthAPI api = new AuthAPI(DOMAIN, CLIENT_ID, CLIENT_SECRET); - assertThat(api.getClient().connectTimeoutMillis(), is(10 * 1000)); - assertThat(api.getClient().readTimeoutMillis(), is(10 * 1000)); - } - - @Test - public void shouldUseConfiguredTimeoutValues() { - HttpOptions options = new HttpOptions(); - options.setConnectTimeout(20); - options.setReadTimeout(30); - AuthAPI api = new AuthAPI(DOMAIN, CLIENT_ID, CLIENT_SECRET, options); - - assertThat(api.getClient().connectTimeoutMillis(), is(20 * 1000)); - assertThat(api.getClient().readTimeoutMillis(), is(30 * 1000)); - } - - @Test - public void shouldUseZeroIfNegativeTimoutConfigured() { - HttpOptions options = new HttpOptions(); - options.setConnectTimeout(-1); - options.setReadTimeout(-10); - AuthAPI api = new AuthAPI(DOMAIN, CLIENT_ID, CLIENT_SECRET, options); - - assertThat(api.getClient().connectTimeoutMillis(), is(0)); - assertThat(api.getClient().readTimeoutMillis(), is(0)); - } - - @Test - public void shouldNotUseProxyByDefault() throws Exception { - AuthAPI api = new AuthAPI(DOMAIN, CLIENT_ID, CLIENT_SECRET); - assertThat(api.getClient().proxy(), is(nullValue())); - Authenticator authenticator = api.getClient().proxyAuthenticator(); - assertThat(authenticator, is(notNullValue())); - - Route route = Mockito.mock(Route.class); - okhttp3.Request nonAuthenticatedRequest = new okhttp3.Request.Builder() - .url("https://test.com/app") - .addHeader("some-header", "some-value") - .build(); - okhttp3.Response nonAuthenticatedResponse = new okhttp3.Response.Builder() - .protocol(Protocol.HTTP_2) - .code(200) - .message("OK") - .request(nonAuthenticatedRequest) - .build(); - - okhttp3.Request processedRequest = authenticator.authenticate(route, nonAuthenticatedResponse); - assertThat(processedRequest, is(nullValue())); - } - - @Test - public void shouldUseProxy() throws Exception { - Proxy proxy = Mockito.mock(Proxy.class); - ProxyOptions proxyOptions = new ProxyOptions(proxy); - HttpOptions httpOptions = new HttpOptions(); - httpOptions.setProxyOptions(proxyOptions); - - AuthAPI api = new AuthAPI(DOMAIN, CLIENT_ID, CLIENT_SECRET, httpOptions); - assertThat(api.getClient().proxy(), is(proxy)); - Authenticator authenticator = api.getClient().proxyAuthenticator(); - assertThat(authenticator, is(notNullValue())); - - Route route = Mockito.mock(Route.class); - okhttp3.Request nonAuthenticatedRequest = new okhttp3.Request.Builder() - .url("https://test.com/app") - .addHeader("some-header", "some-value") - .build(); - okhttp3.Response nonAuthenticatedResponse = new okhttp3.Response.Builder() - .protocol(Protocol.HTTP_2) - .code(200) - .message("OK") - .request(nonAuthenticatedRequest) - .build(); - - okhttp3.Request processedRequest = authenticator.authenticate(route, nonAuthenticatedResponse); - - assertThat(processedRequest, is(nullValue())); - } - - @Test - public void shouldUseProxyWithAuthentication() throws Exception { - Proxy proxy = Mockito.mock(Proxy.class); - ProxyOptions proxyOptions = new ProxyOptions(proxy); - proxyOptions.setBasicAuthentication("johndoe", "psswd".toCharArray()); - assertThat(proxyOptions.getBasicAuthentication(), is("Basic am9obmRvZTpwc3N3ZA==")); - HttpOptions httpOptions = new HttpOptions(); - httpOptions.setProxyOptions(proxyOptions); - - AuthAPI api = new AuthAPI(DOMAIN, CLIENT_ID, CLIENT_SECRET, httpOptions); - assertThat(api.getClient().proxy(), is(proxy)); - Authenticator authenticator = api.getClient().proxyAuthenticator(); - assertThat(authenticator, is(notNullValue())); - - Route route = Mockito.mock(Route.class); - okhttp3.Request nonAuthenticatedRequest = new okhttp3.Request.Builder() - .url("https://test.com/app") - .addHeader("some-header", "some-value") - .build(); - okhttp3.Response nonAuthenticatedResponse = new okhttp3.Response.Builder() - .protocol(Protocol.HTTP_2) - .code(200) - .message("OK") - .request(nonAuthenticatedRequest) - .build(); - - okhttp3.Request processedRequest = authenticator.authenticate(route, nonAuthenticatedResponse); - - assertThat(processedRequest, is(notNullValue())); - assertThat(processedRequest.url(), is(HttpUrl.parse("https://test.com/app"))); - assertThat(processedRequest.header("Proxy-Authorization"), is(proxyOptions.getBasicAuthentication())); - assertThat(processedRequest.header("some-header"), is("some-value")); - } - - @Test - public void proxyShouldNotProcessAlreadyAuthenticatedRequest() throws Exception { - Proxy proxy = Mockito.mock(Proxy.class); - ProxyOptions proxyOptions = new ProxyOptions(proxy); - proxyOptions.setBasicAuthentication("johndoe", "psswd".toCharArray()); - assertThat(proxyOptions.getBasicAuthentication(), is("Basic am9obmRvZTpwc3N3ZA==")); - HttpOptions httpOptions = new HttpOptions(); - httpOptions.setProxyOptions(proxyOptions); - - AuthAPI api = new AuthAPI(DOMAIN, CLIENT_ID, CLIENT_SECRET, httpOptions); - assertThat(api.getClient().proxy(), is(proxy)); - Authenticator authenticator = api.getClient().proxyAuthenticator(); - assertThat(authenticator, is(notNullValue())); - - Route route = Mockito.mock(Route.class); - okhttp3.Request alreadyAuthenticatedRequest = new okhttp3.Request.Builder() - .url("https://test.com/app") - .addHeader("some-header", "some-value") - .header("Proxy-Authorization", "pre-existing-value") - .build(); - okhttp3.Response alreadyAuthenticatedResponse = new okhttp3.Response.Builder() - .protocol(Protocol.HTTP_2) - .code(200) - .message("OK") - .request(alreadyAuthenticatedRequest) - .build(); - - okhttp3.Request processedRequest = authenticator.authenticate(route, alreadyAuthenticatedResponse); - assertThat(processedRequest, is(nullValue())); - } - - @Test - public void shouldUseCustomTelemetry() { - AuthAPI api = new AuthAPI(DOMAIN, CLIENT_ID, CLIENT_SECRET); - assertThat(api.getClient().interceptors(), hasItem(isA(TelemetryInterceptor.class))); - - Telemetry currentTelemetry = null; - for (Interceptor i : api.getClient().interceptors()) { - if (i instanceof TelemetryInterceptor) { - TelemetryInterceptor interceptor = (TelemetryInterceptor) i; - currentTelemetry = interceptor.getTelemetry(); - } - } - assertThat(currentTelemetry, is(notNullValue())); - - Telemetry newTelemetry = Mockito.mock(Telemetry.class); - api.setTelemetry(newTelemetry); - - Telemetry updatedTelemetry = null; - for (Interceptor i : api.getClient().interceptors()) { - if (i instanceof TelemetryInterceptor) { - TelemetryInterceptor interceptor = (TelemetryInterceptor) i; - updatedTelemetry = interceptor.getTelemetry(); - } - } - assertThat(updatedTelemetry, is(newTelemetry)); - } - - @Test - public void shouldAddAndEnableTelemetryInterceptor() { - AuthAPI api = new AuthAPI(DOMAIN, CLIENT_ID, CLIENT_SECRET); - assertThat(api.getClient().interceptors(), hasItem(isA(TelemetryInterceptor.class))); - - for (Interceptor i : api.getClient().interceptors()) { - if (i instanceof TelemetryInterceptor) { - TelemetryInterceptor telemetry = (TelemetryInterceptor) i; - assertThat(telemetry.isEnabled(), is(true)); - } - } - } - - @Test - public void shouldDisableTelemetryInterceptor() { - AuthAPI api = new AuthAPI(DOMAIN, CLIENT_ID, CLIENT_SECRET); - assertThat(api.getClient().interceptors(), hasItem(isA(TelemetryInterceptor.class))); - api.doNotSendTelemetry(); - - for (Interceptor i : api.getClient().interceptors()) { - if (i instanceof TelemetryInterceptor) { - TelemetryInterceptor telemetry = (TelemetryInterceptor) i; - assertThat(telemetry.isEnabled(), is(false)); - } - } - } - - @Test - public void shouldAddAndDisableLoggingInterceptor() { - AuthAPI api = new AuthAPI(DOMAIN, CLIENT_ID, CLIENT_SECRET); - assertThat(api.getClient().interceptors(), hasItem(isA(HttpLoggingInterceptor.class))); - - for (Interceptor i : api.getClient().interceptors()) { - if (i instanceof HttpLoggingInterceptor) { - HttpLoggingInterceptor logging = (HttpLoggingInterceptor) i; - assertThat(logging.getLevel(), is(Level.NONE)); - } - } - } - @Test @SuppressWarnings("deprecation") - public void shouldEnableLoggingInterceptor() { - AuthAPI api = new AuthAPI(DOMAIN, CLIENT_ID, CLIENT_SECRET); - assertThat(api.getClient().interceptors(), hasItem(isA(HttpLoggingInterceptor.class))); - api.setLoggingEnabled(true); - - for (Interceptor i : api.getClient().interceptors()) { - if (i instanceof HttpLoggingInterceptor) { - HttpLoggingInterceptor logging = (HttpLoggingInterceptor) i; - assertThat(logging.getLevel(), is(Level.BODY)); - } - } + public void shouldAcceptHttpOptions() { + AuthAPI api = new AuthAPI(DOMAIN, CLIENT_ID, CLIENT_SECRET, new com.auth0.client.HttpOptions()); + assertThat(api, is(notNullValue())); } @Test - @SuppressWarnings("deprecation") - public void shouldDisableLoggingInterceptor() { - AuthAPI api = new AuthAPI(DOMAIN, CLIENT_ID, CLIENT_SECRET); - assertThat(api.getClient().interceptors(), hasItem(isA(HttpLoggingInterceptor.class))); - api.setLoggingEnabled(false); - - for (Interceptor i : api.getClient().interceptors()) { - if (i instanceof HttpLoggingInterceptor) { - HttpLoggingInterceptor logging = (HttpLoggingInterceptor) i; - assertThat(logging.getLevel(), is(Level.NONE)); + public void shouldAcceptHttpClient() { + Auth0HttpClient httpClient = new Auth0HttpClient() { + @Override + public Auth0HttpResponse sendRequest(Auth0HttpRequest request) { + return null; } - } - } - @Test - public void shouldConfigureNoneLoggingFromOptions() { - LoggingOptions loggingOptions = new LoggingOptions(LoggingOptions.LogLevel.NONE); - HttpOptions options = new HttpOptions(); - options.setLoggingOptions(loggingOptions); - - AuthAPI api = new AuthAPI(DOMAIN, CLIENT_ID, CLIENT_SECRET, options); - assertThat(api.getClient().interceptors(), hasItem(isA(HttpLoggingInterceptor.class))); - - for (Interceptor i : api.getClient().interceptors()) { - if (i instanceof HttpLoggingInterceptor) { - HttpLoggingInterceptor logging = (HttpLoggingInterceptor) i; - assertThat(logging.getLevel(), is(Level.NONE)); + @Override + public CompletableFuture sendRequestAsync(Auth0HttpRequest request) { + return null; } - } - } - - @Test - public void shouldConfigureBasicLoggingFromOptions() { - LoggingOptions loggingOptions = new LoggingOptions(LoggingOptions.LogLevel.BASIC); - HttpOptions options = new HttpOptions(); - options.setLoggingOptions(loggingOptions); + }; - AuthAPI api = new AuthAPI(DOMAIN, CLIENT_ID, CLIENT_SECRET, options); - assertThat(api.getClient().interceptors(), hasItem(isA(HttpLoggingInterceptor.class))); + AuthAPI api = AuthAPI.newBuilder(DOMAIN, CLIENT_ID, CLIENT_SECRET) + .withHttpClient(httpClient) + .build(); - for (Interceptor i : api.getClient().interceptors()) { - if (i instanceof HttpLoggingInterceptor) { - HttpLoggingInterceptor logging = (HttpLoggingInterceptor) i; - assertThat(logging.getLevel(), is(Level.BASIC)); - } - } + assertThat(api, is(notNullValue())); + assertThat(api.getHttpClient(), is(notNullValue())); } @Test - public void shouldConfigureHeaderLoggingFromOptions() { - LoggingOptions loggingOptions = new LoggingOptions(LoggingOptions.LogLevel.HEADERS); - Set headersToRedact = new HashSet<>(); - headersToRedact.add("Authorization"); - headersToRedact.add("Cookie"); - loggingOptions.setHeadersToRedact(headersToRedact); - HttpOptions options = new HttpOptions(); - options.setLoggingOptions(loggingOptions); - - AuthAPI api = new AuthAPI(DOMAIN, CLIENT_ID, CLIENT_SECRET, options); - assertThat(api.getClient().interceptors(), hasItem(isA(HttpLoggingInterceptor.class))); + public void shouldAcceptDomainWithNoScheme() { + AuthAPI api = AuthAPI.newBuilder("me.something.com", CLIENT_ID, CLIENT_SECRET).build(); - for (Interceptor i : api.getClient().interceptors()) { - if (i instanceof HttpLoggingInterceptor) { - HttpLoggingInterceptor logging = (HttpLoggingInterceptor) i; - assertThat(logging.getLevel(), is(Level.HEADERS)); - } - } + assertThat(api.getBaseUrl(), is(notNullValue())); + assertThat(api.getBaseUrl().toString(), isUrl("https", "me.something.com")); } @Test - public void shouldConfigureBodyLoggingFromOptions() { - LoggingOptions loggingOptions = new LoggingOptions(LoggingOptions.LogLevel.BODY); - Set headersToRedact = new HashSet<>(); - headersToRedact.add("Authorization"); - headersToRedact.add("Cookie"); - loggingOptions.setHeadersToRedact(headersToRedact); - HttpOptions options = new HttpOptions(); - options.setLoggingOptions(loggingOptions); - - AuthAPI api = new AuthAPI(DOMAIN, CLIENT_ID, CLIENT_SECRET, options); - assertThat(api.getClient().interceptors(), hasItem(isA(HttpLoggingInterceptor.class))); - - for (Interceptor i : api.getClient().interceptors()) { - if (i instanceof HttpLoggingInterceptor) { - HttpLoggingInterceptor logging = (HttpLoggingInterceptor) i; - assertThat(logging.getLevel(), is(Level.BODY)); - } - } - } + public void shouldAcceptDomainWithHttpScheme() { + AuthAPI api = AuthAPI.newBuilder("http://me.something.com", CLIENT_ID, CLIENT_SECRET).build(); - @Test - public void shouldUseDefaultMaxRequests() { - AuthAPI api = new AuthAPI(DOMAIN, CLIENT_ID, CLIENT_SECRET); - assertThat(api.getClient().dispatcher().getMaxRequests(), is(64)); + assertThat(api.getBaseUrl(), is(notNullValue())); + assertThat(api.getBaseUrl().toString(), isUrl("http", "me.something.com")); } @Test - public void shouldUseConfiguredMaxRequests() { - HttpOptions options = new HttpOptions(); - options.setMaxRequests(10); - AuthAPI api = new AuthAPI(DOMAIN, CLIENT_ID, CLIENT_SECRET, options); - assertThat(api.getClient().dispatcher().getMaxRequests(), is(10)); + public void shouldThrowWhenDomainIsInvalid() { + verifyThrows(IllegalArgumentException.class, + () -> AuthAPI.newBuilder("", CLIENT_ID, CLIENT_SECRET).build(), + "The domain had an invalid format and couldn't be parsed as an URL."); } @Test - public void shouldThrowOnInValidMaxRequestsConfiguration() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("maxRequests must be one or greater."); - - HttpOptions options = new HttpOptions(); - options.setMaxRequests(0); + public void shouldThrowWhenDomainIsNull() { + verifyThrows(IllegalArgumentException.class, + () -> AuthAPI.newBuilder(null, CLIENT_ID, CLIENT_SECRET).build(), + "'domain' cannot be null!"); } @Test - public void shouldUseDefaultMaxRequestsPerHost() { - AuthAPI api = new AuthAPI(DOMAIN, CLIENT_ID, CLIENT_SECRET); - assertThat(api.getClient().dispatcher().getMaxRequestsPerHost(), is(5)); + public void shouldThrowWhenClientIdIsNull() { + verifyThrows(IllegalArgumentException.class, + () -> AuthAPI.newBuilder(DOMAIN, null, CLIENT_SECRET).build(), + "'client id' cannot be null!"); } @Test - public void shouldUseConfiguredMaxRequestsPerHost() { - HttpOptions options = new HttpOptions(); - options.setMaxRequestsPerHost(10); - AuthAPI api = new AuthAPI(DOMAIN, CLIENT_ID, CLIENT_SECRET, options); - assertThat(api.getClient().dispatcher().getMaxRequestsPerHost(), is(10)); + public void shouldAcceptNullClientSecret() { + assertThat(AuthAPI.newBuilder(DOMAIN, CLIENT_ID, (String) null).build(), + is(notNullValue())); } @Test + @SuppressWarnings("deprecation") public void shouldThrowOnInValidMaxRequestsPerHostConfiguration() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("maxRequestsPerHost must be one or greater."); - - HttpOptions options = new HttpOptions(); - options.setMaxRequestsPerHost(0); + com.auth0.client.HttpOptions options = new com.auth0.client.HttpOptions(); + verifyThrows(IllegalArgumentException.class, + () -> options.setMaxRequestsPerHost(0), + "maxRequestsPerHost must be one or greater."); } //Authorize @Test public void shouldThrowWhenAuthorizeUrlBuilderRedirectUriIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'redirect uri' must be a valid URL!"); - api.authorizeUrl(null); + verifyThrows(IllegalArgumentException.class, + () -> api.authorizeUrl(null), + "'redirect uri' must be a valid URL!"); } @Test public void shouldThrowWhenAuthorizeUrlBuilderRedirectUriIsNotValidURL() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'redirect uri' must be a valid URL!"); - api.authorizeUrl("notvalid.url"); + verifyThrows(IllegalArgumentException.class, + () -> api.authorizeUrl("notvalid.url"), + "'redirect uri' must be a valid URL!"); } @Test @@ -496,7 +171,7 @@ public void shouldGetAuthorizeUrlBuilder() { @Test public void shouldSetAuthorizeUrlBuilderDefaultValues() { - AuthAPI api = new AuthAPI("domain.auth0.com", CLIENT_ID, CLIENT_SECRET); + AuthAPI api = AuthAPI.newBuilder("domain.auth0.com", CLIENT_ID, CLIENT_SECRET).build(); String url = api.authorizeUrl("https://domain.auth0.com/callback").build(); assertThat(url, isUrl("https", "domain.auth0.com", "/authorize")); @@ -511,16 +186,16 @@ public void shouldSetAuthorizeUrlBuilderDefaultValues() { @Test public void shouldThrowWhenLogoutUrlBuilderReturnToUrlIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'return to url' must be a valid URL!"); - api.logoutUrl(null, true); + verifyThrows(IllegalArgumentException.class, + () -> api.logoutUrl(null, true), + "'return to url' must be a valid URL!"); } @Test public void shouldThrowWhenLogoutUrlBuilderRedirectUriIsNotValidURL() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'return to url' must be a valid URL!"); - api.logoutUrl("notvalid.url", true); + verifyThrows(IllegalArgumentException.class, + () -> api.logoutUrl("notvalid.url", true), + "'return to url' must be a valid URL!"); } @Test @@ -531,7 +206,7 @@ public void shouldGetLogoutUrlBuilder() { @Test public void shouldSetLogoutUrlBuilderDefaultValues() { - AuthAPI api = new AuthAPI("domain.auth0.com", CLIENT_ID, CLIENT_SECRET); + AuthAPI api = AuthAPI.newBuilder("domain.auth0.com", CLIENT_ID, CLIENT_SECRET).build(); String url = api.logoutUrl("https://my.domain.com/welcome", false).build(); assertThat(url, isUrl("https", "domain.auth0.com", "/v2/logout")); @@ -541,7 +216,7 @@ public void shouldSetLogoutUrlBuilderDefaultValues() { @Test public void shouldSetLogoutUrlBuilderDefaultValuesAndClientId() { - AuthAPI api = new AuthAPI("domain.auth0.com", CLIENT_ID, CLIENT_SECRET); + AuthAPI api = AuthAPI.newBuilder("domain.auth0.com", CLIENT_ID, CLIENT_SECRET).build(); String url = api.logoutUrl("https://my.domain.com/welcome", true).build(); assertThat(url, isUrl("https", "domain.auth0.com", "/v2/logout")); @@ -554,9 +229,9 @@ public void shouldSetLogoutUrlBuilderDefaultValuesAndClientId() { @Test public void shouldThrowOnUserInfoWithNullAccessToken() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'access token' cannot be null!"); - api.userInfo(null); + verifyThrows(IllegalArgumentException.class, + () -> api.userInfo(null), + "'access token' cannot be null!"); } @Test @@ -565,10 +240,10 @@ public void shouldCreateUserInfoRequest() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(AUTH_USER_INFO, 200); - UserInfo response = request.execute(); + UserInfo response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/userinfo")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/userinfo")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer accessToken")); @@ -585,6 +260,7 @@ public void shouldCreateUserInfoRequest() throws Exception { assertThat(response.getValues(), hasEntry("created_at", "2016-12-05T11:16:59.640Z")); assertThat(response.getValues(), hasEntry("sub", "auth0|58454...")); assertThat(response.getValues(), hasKey("identities")); + @SuppressWarnings("unchecked") List> identities = (List>) response.getValues().get("identities"); assertThat(identities, hasSize(1)); assertThat(identities.get(0), hasEntry("user_id", "58454...")); @@ -598,16 +274,16 @@ public void shouldCreateUserInfoRequest() throws Exception { @Test public void shouldThrowOnResetPasswordWithNullEmail() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'email' cannot be null!"); - api.resetPassword(null, "my-connection"); + verifyThrows(IllegalArgumentException.class, + () -> api.resetPassword(null, "my-connection"), + "'email' cannot be null!"); } @Test public void shouldThrowOnResetPasswordWithNullConnection() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'connection' cannot be null!"); - api.resetPassword("me@auth0.com", null); + verifyThrows(IllegalArgumentException.class, + () -> api.resetPassword("me@auth0.com", null), + "'connection' cannot be null!"); } @Test @@ -616,10 +292,10 @@ public void shouldCreateResetPasswordRequest() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(AUTH_RESET_PASSWORD, 200); - Void response = request.execute(); + Void response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/dbconnections/change_password")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/dbconnections/change_password")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); Map body = bodyFromRequest(recordedRequest); @@ -631,77 +307,126 @@ public void shouldCreateResetPasswordRequest() throws Exception { assertThat(response, is(nullValue())); } + @Test + public void shouldCreateResetPasswordRequestWithSpecifiedClientId() throws Exception { + Request request = api.resetPassword("CLIENT-ID", "me@auth0.com", "db-connection"); + assertThat(request, is(notNullValue())); + + server.jsonResponse(AUTH_RESET_PASSWORD, 200); + Void response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/dbconnections/change_password")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + + Map body = bodyFromRequest(recordedRequest); + assertThat(body, hasEntry("email", "me@auth0.com")); + assertThat(body, hasEntry("connection", "db-connection")); + assertThat(body, hasEntry("client_id", "CLIENT-ID")); + assertThat(body, not(hasKey("password"))); + + assertThat(response, is(nullValue())); + } + + @Test + public void shouldCreateResetPasswordRequestWithSpecifiedClientIdWithOrganization() throws Exception { + Request request = api.resetPassword("CLIENT-ID", "me@auth0.com", "db-connection", "ORGANIZATION-ID"); + assertThat(request, is(notNullValue())); + + server.jsonResponse(AUTH_RESET_PASSWORD, 200); + Void response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/dbconnections/change_password")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + + Map body = bodyFromRequest(recordedRequest); + assertThat(body, hasEntry("email", "me@auth0.com")); + assertThat(body, hasEntry("connection", "db-connection")); + assertThat(body, hasEntry("client_id", "CLIENT-ID")); + assertThat(body, hasEntry("organization", "ORGANIZATION-ID")); + assertThat(body, not(hasKey("password"))); + + assertThat(response, is(nullValue())); + } //Sign Up @SuppressWarnings("deprecation") @Test public void shouldThrowOnSignUpWithNullEmail() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'email' cannot be null!"); - api.signUp(null, "p455w0rd", "my-connection"); + verifyThrows(IllegalArgumentException.class, + () -> api.signUp(null, "p455w0rd", "my-connection"), + "'email' cannot be null!"); } @SuppressWarnings("deprecation") @Test public void shouldThrowOnSignUpWithNullPasswordString() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'password' cannot be null!"); - api.signUp("me@auth0.com", (String) null, "my-connection"); + verifyThrows(IllegalArgumentException.class, + () -> api.signUp("me@auth0.com", (String) null, "my-connection"), + "'password' cannot be null!"); } @Test public void shouldThrowOnSignUpWithNullPasswordCharArray() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'password' cannot be null!"); - api.signUp("me@auth0.com", (char[]) null, "my-connection"); + verifyThrows(IllegalArgumentException.class, + () -> api.signUp("me@auth0.com", (char[]) null, "my-connection"), + "'password' cannot be null!"); } @SuppressWarnings("deprecation") @Test public void shouldThrowOnSignUpWithNullConnection() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'connection' cannot be null!"); - api.signUp("me@auth0.com", "p455w0rd", null); + verifyThrows(IllegalArgumentException.class, + () -> api.signUp("me@auth0.com", "p455w0rd", null), + "'connection' cannot be null!"); } @SuppressWarnings("deprecation") @Test public void shouldThrowOnUsernameSignUpWithNullEmail() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'email' cannot be null!"); - api.signUp(null, "me", "p455w0rd", "my-connection"); + verifyThrows(IllegalArgumentException.class, + () -> api.signUp(null, "me", "p455w0rd", "my-connection"), + "'email' cannot be null!"); } @SuppressWarnings("deprecation") @Test public void shouldThrowOnUsernameSignUpWithNullUsername() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'username' cannot be null!"); - api.signUp("me@auth0.com", null, "p455w0rd", "my-connection"); + verifyThrows(IllegalArgumentException.class, + () -> api.signUp("me@auth0.com", null, "p455w0rd", "my-connection"), + "'username' cannot be null!"); } @SuppressWarnings("deprecation") @Test public void shouldThrowOnUsernameSignUpWithNullPasswordString() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'password' cannot be null!"); - api.signUp("me@auth0.com", "me", (String) null, "my-connection"); + verifyThrows(IllegalArgumentException.class, + () -> api.signUp("me@auth0.com", "me", (String) null, "my-connection"), + "'password' cannot be null!"); } @Test public void shouldThrowOnUsernameSignUpWithNullPasswordCharArray() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'password' cannot be null!"); - api.signUp("me@auth0.com", "me", (char[]) null, "my-connection"); + verifyThrows(IllegalArgumentException.class, + () -> api.signUp("me@auth0.com", "me", (char[]) null, "my-connection"), + "'password' cannot be null!"); } @SuppressWarnings("deprecation") @Test public void shouldThrowOnUsernameSignUpWithNullConnection() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'connection' cannot be null!"); - api.signUp("me@auth0.com", "me", "p455w0rd", null); + verifyThrows(IllegalArgumentException.class, + () -> api.signUp("me@auth0.com", "me", "p455w0rd", null), + "'connection' cannot be null!"); + } + + @Test + public void shouldThrowOnUsernameAndPhoneNumberSignUpWithNullPhoneNumber() { + verifyThrows(IllegalArgumentException.class, + () -> api.signUp("me@auth0.com", "me", new char[]{'p','4','5','5','w','0','r','d'}, "my-connection", null), + "'phone number' cannot be null!"); } @Test @@ -728,6 +453,34 @@ public void shouldHaveNotStrongPasswordWithShortDetailedDescription() throws Exc assertThat(ex.getDescription(), is(expectedDescription)); } + @Test + public void shouldCreateSignUpRequestWithUsernameAndPhoneNumber() throws Exception { + SignUpRequest request = api.signUp("me@auth0.com", "me", new char[]{'p','4','5','5','w','0','r','d'}, "db-connection", "1234567890"); + assertThat(request, is(notNullValue())); + + server.jsonResponse(AUTH_SIGN_UP_USERNAME, 200); + CreatedUser response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/dbconnections/signup")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + + Map body = bodyFromRequest(recordedRequest); + assertThat(body, hasEntry("email", "me@auth0.com")); + assertThat(body, hasEntry("username", "me")); + assertThat(body, hasEntry("password", "p455w0rd")); + assertThat(body, hasEntry("connection", "db-connection")); + assertThat(body, hasEntry("client_id", CLIENT_ID)); + assertThat(body, hasEntry("phone_number", "1234567890")); + + assertThat(response, is(notNullValue())); + assertThat(response.getUserId(), is("58457fe6b27")); + assertThat(response.getEmail(), is("me@auth0.com")); + assertThat(response.isEmailVerified(), is(false)); + assertThat(response.getUsername(), is("me")); + assertThat(response.getPhoneNumber(), is("1234567890")); + } + @Test public void shouldCreateSignUpRequestWithUsername() throws Exception { @SuppressWarnings("deprecation") @@ -735,10 +488,10 @@ public void shouldCreateSignUpRequestWithUsername() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(AUTH_SIGN_UP_USERNAME, 200); - CreatedUser response = request.execute(); + CreatedUser response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/dbconnections/signup")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/dbconnections/signup")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); Map body = bodyFromRequest(recordedRequest); @@ -763,10 +516,10 @@ public void shouldCreateSignUpRequest() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(AUTH_SIGN_UP, 200); - CreatedUser response = request.execute(); + CreatedUser response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/dbconnections/signup")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/dbconnections/signup")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); Map body = bodyFromRequest(recordedRequest); @@ -794,10 +547,10 @@ public void shouldCreateSignUpRequestWithCustomParameters() throws Exception { request.setCustomFields(customFields); server.jsonResponse(AUTH_SIGN_UP, 200); - CreatedUser response = request.execute(); + CreatedUser response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/dbconnections/signup")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/dbconnections/signup")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); Map body = bodyFromRequest(recordedRequest); @@ -806,6 +559,7 @@ public void shouldCreateSignUpRequestWithCustomParameters() throws Exception { assertThat(body, hasEntry("connection", "db-connection")); assertThat(body, hasEntry("client_id", CLIENT_ID)); assertThat(body, hasKey("user_metadata")); + @SuppressWarnings("unchecked") Map metadata = (Map) body.get("user_metadata"); assertThat(metadata, hasEntry("age", "25")); assertThat(metadata, hasEntry("address", "123, fake street")); @@ -823,28 +577,28 @@ public void shouldCreateSignUpRequestWithCustomParameters() throws Exception { @Test public void shouldThrowOnLogInWithAuthorizationCodeGrantAndRedirectUriWithNullCode() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'code' cannot be null!"); - api.exchangeCode(null, "https://domain.auth0.com/callback"); + verifyThrows(IllegalArgumentException.class, + () -> api.exchangeCode(null, "https://domain.auth0.com/callback"), + "'code' cannot be null!"); } @Test public void shouldThrowOnLogInWithAuthorizationCodeGrantAndRedirectUriWithNullRedirectUri() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'redirect uri' cannot be null!"); - api.exchangeCode("code", null); + verifyThrows(IllegalArgumentException.class, + () -> api.exchangeCode("code", null), + "'redirect uri' cannot be null!"); } @Test public void shouldCreateLogInWithAuthorizationCodeGrantRequest() throws Exception { - AuthRequest request = api.exchangeCode("code123", "https://domain.auth0.com/callback"); + TokenRequest request = api.exchangeCode("code123", "https://domain.auth0.com/callback"); assertThat(request, is(notNullValue())); server.jsonResponse(AUTH_TOKENS, 200); - TokenHolder response = request.execute(); + TokenHolder response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/oauth/token")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/oauth/token")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); Map body = bodyFromRequest(recordedRequest); @@ -862,19 +616,26 @@ public void shouldCreateLogInWithAuthorizationCodeGrantRequest() throws Exceptio assertThat(response.getExpiresIn(), is(notNullValue())); } + @Test + public void authorizationCodeGrantRequestRequiresClientAuthentication() { + verifyThrows(IllegalStateException.class, + () -> apiNoClientAuthentication.exchangeCode("code", "https://domain.auth0.com/callback"), + "A client secret or client assertion signing key is required for this operation"); + } + @Test public void shouldCreateLogInWithAuthorizationCodeGrantRequestWithCustomParameters() throws Exception { - AuthRequest request = api.exchangeCode("code123", "https://domain.auth0.com/callback"); + TokenRequest request = api.exchangeCode("code123", "https://domain.auth0.com/callback"); assertThat(request, is(notNullValue())); request.setAudience("https://myapi.auth0.com/users"); request.setRealm("dbconnection"); request.setScope("profile photos contacts"); server.jsonResponse(AUTH_TOKENS, 200); - TokenHolder response = request.execute(); + TokenHolder response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/oauth/token")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/oauth/token")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); Map body = bodyFromRequest(recordedRequest); @@ -901,37 +662,37 @@ public void shouldCreateLogInWithAuthorizationCodeGrantRequestWithCustomParamete @SuppressWarnings("deprecation") @Test public void shouldThrowOnLogInWithPasswordWithNullUsername() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'email or username' cannot be null!"); - api.login(null, "p455w0rd"); + verifyThrows(IllegalArgumentException.class, + () -> api.login(null, "p455w0rd"), + "'email or username' cannot be null!"); } @SuppressWarnings("deprecation") @Test public void shouldThrowOnLogInWithPasswordWithNullPassword() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'password' cannot be null!"); - api.login("me", (String) null); + verifyThrows(IllegalArgumentException.class, + () -> api.login("me", (String) null), + "'password' cannot be null!"); } @Test public void shouldThrowOnLogInWithCharPasswordWithNullPassword() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'password' cannot be null!"); - api.login("me", (char[]) null); + verifyThrows(IllegalArgumentException.class, + () -> api.login("me", (char[]) null), + "'password' cannot be null!"); } @Test public void shouldCreateLogInWithPasswordGrantRequest() throws Exception { @SuppressWarnings("deprecation") - AuthRequest request = api.login("me", "p455w0rd"); + TokenRequest request = api.login("me", "p455w0rd"); assertThat(request, is(notNullValue())); server.jsonResponse(AUTH_TOKENS, 200); - TokenHolder response = request.execute(); + TokenHolder response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/oauth/token")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/oauth/token")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); Map body = bodyFromRequest(recordedRequest); @@ -949,20 +710,28 @@ public void shouldCreateLogInWithPasswordGrantRequest() throws Exception { assertThat(response.getExpiresIn(), is(notNullValue())); } + @Test + @SuppressWarnings("deprecation") + public void passwordGrantRequestRequiresClientAuthentication() { + verifyThrows(IllegalStateException.class, + () -> apiNoClientAuthentication.login("me", "p455w0rd"), + "A client secret or client assertion signing key is required for this operation"); + } + @Test public void shouldCreateLogInWithPasswordGrantRequestWithCustomParameters() throws Exception { @SuppressWarnings("deprecation") - AuthRequest request = api.login("me", "p455w0rd"); + TokenRequest request = api.login("me", "p455w0rd"); assertThat(request, is(notNullValue())); request.setRealm("dbconnection"); request.setScope("profile photos contacts"); request.setAudience("https://myapi.auth0.com/users"); server.jsonResponse(AUTH_TOKENS, 200); - TokenHolder response = request.execute(); + TokenHolder response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/oauth/token")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/oauth/token")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); Map body = bodyFromRequest(recordedRequest); @@ -989,10 +758,10 @@ public void shouldSetCustomHeaderWithPasswordlessRealmRequest() throws Exception request.addHeader("some-header", "some-value"); server.jsonResponse(AUTH_TOKENS, 200); - TokenHolder response = request.execute(); + TokenHolder response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/oauth/token")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/oauth/token")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("some-header", "some-value")); @@ -1016,45 +785,45 @@ public void shouldSetCustomHeaderWithPasswordlessRealmRequest() throws Exception @SuppressWarnings("deprecation") @Test public void shouldThrowOnLogInWithPasswordRealmWithNullUsername() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'email or username' cannot be null!"); - api.login(null, "p455w0rd", "realm"); + verifyThrows(IllegalArgumentException.class, + () -> api.login(null, "p455w0rd", "realm"), + "'email or username' cannot be null!"); } @SuppressWarnings("deprecation") @Test public void shouldThrowOnLogInWithPasswordRealmWithNullPasswordString() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'password' cannot be null!"); - api.login("me", (String) null, "realm"); + verifyThrows(IllegalArgumentException.class, + () -> api.login("me", (String) null, "realm"), + "'password' cannot be null!"); } @Test public void shouldThrowOnLogInWithPasswordRealmWithNullPasswordCharArray() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'password' cannot be null!"); - api.login("me", (char[]) null, "realm"); + verifyThrows(IllegalArgumentException.class, + () -> api.login("me", (char[]) null, "realm"), + "'password' cannot be null!"); } @SuppressWarnings("deprecation") @Test public void shouldThrowOnLogInWithPasswordRealmWithNullRealm() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'realm' cannot be null!"); - api.login("me", "p455w0rd", null); + verifyThrows(IllegalArgumentException.class, + () -> api.login("me", "p455w0rd", null), + "'realm' cannot be null!"); } @Test public void shouldCreateLogInWithPasswordRealmGrantRequest() throws Exception { @SuppressWarnings("deprecation") - AuthRequest request = api.login("me", "p455w0rd", "realm"); + TokenRequest request = api.login("me", "p455w0rd", "realm"); assertThat(request, is(notNullValue())); server.jsonResponse(AUTH_TOKENS, 200); - TokenHolder response = request.execute(); + TokenHolder response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/oauth/token")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/oauth/token")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); Map body = bodyFromRequest(recordedRequest); @@ -1073,20 +842,28 @@ public void shouldCreateLogInWithPasswordRealmGrantRequest() throws Exception { assertThat(response.getExpiresIn(), is(notNullValue())); } + @Test + @SuppressWarnings("deprecation") + public void passwordRealmGrantRequestRequiresClientAuthentication() { + verifyThrows(IllegalStateException.class, + () -> apiNoClientAuthentication.login("me", "p455w0rd", "realm"), + "A client secret or client assertion signing key is required for this operation"); + } + @Test public void shouldCreateLogInWithPasswordRealmGrantRequestWithCustomParameters() throws Exception { @SuppressWarnings("deprecation") - AuthRequest request = api.login("me", "p455w0rd", "realm"); + TokenRequest request = api.login("me", "p455w0rd", "realm"); assertThat(request, is(notNullValue())); request.setAudience("https://myapi.auth0.com/users"); request.setRealm("dbconnection"); request.setScope("profile photos contacts"); server.jsonResponse(AUTH_TOKENS, 200); - TokenHolder response = request.execute(); + TokenHolder response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/oauth/token")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/oauth/token")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); Map body = bodyFromRequest(recordedRequest); @@ -1112,21 +889,75 @@ public void shouldCreateLogInWithPasswordRealmGrantRequestWithCustomParameters() @Test public void shouldThrowOnLogInWithClientCredentialsWithNullAudience() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'audience' cannot be null!"); - api.requestToken(null); + verifyThrows(IllegalArgumentException.class, + () -> api.requestToken(null), + "'audience' cannot be null!"); } @Test public void shouldCreateLogInWithClientCredentialsGrantRequest() throws Exception { - AuthRequest request = api.requestToken("https://myapi.auth0.com/users"); + TokenRequest request = api.requestToken("https://myapi.auth0.com/users"); + assertThat(request, is(notNullValue())); + + server.jsonResponse(AUTH_TOKENS, 200); + TokenHolder response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/oauth/token")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + + Map body = bodyFromRequest(recordedRequest); + assertThat(body, hasEntry("grant_type", "client_credentials")); + assertThat(body, hasEntry("client_id", CLIENT_ID)); + assertThat(body, hasEntry("client_secret", CLIENT_SECRET)); + assertThat(body, hasEntry("audience", "https://myapi.auth0.com/users")); + assertThat(body, not(hasEntry("organization", any(String.class)))); + + assertThat(response, is(notNullValue())); + assertThat(response.getAccessToken(), not(emptyOrNullString())); + assertThat(response.getIdToken(), not(emptyOrNullString())); + assertThat(response.getRefreshToken(), not(emptyOrNullString())); + assertThat(response.getTokenType(), not(emptyOrNullString())); + assertThat(response.getExpiresIn(), is(notNullValue())); + } + + @Test + public void shouldCreateLogInWithClientCredentialsGrantRequestWithOrg() throws Exception { + TokenRequest request = api.requestToken("https://myapi.auth0.com/users", "org_123"); + assertThat(request, is(notNullValue())); + + server.jsonResponse(AUTH_TOKENS, 200); + TokenHolder response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/oauth/token")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + + Map body = bodyFromRequest(recordedRequest); + assertThat(body, hasEntry("grant_type", "client_credentials")); + assertThat(body, hasEntry("client_id", CLIENT_ID)); + assertThat(body, hasEntry("client_secret", CLIENT_SECRET)); + assertThat(body, hasEntry("audience", "https://myapi.auth0.com/users")); + assertThat(body, hasEntry("organization", "org_123")); + + assertThat(response, is(notNullValue())); + assertThat(response.getAccessToken(), not(emptyOrNullString())); + assertThat(response.getIdToken(), not(emptyOrNullString())); + assertThat(response.getRefreshToken(), not(emptyOrNullString())); + assertThat(response.getTokenType(), not(emptyOrNullString())); + assertThat(response.getExpiresIn(), is(notNullValue())); + } + + @Test + public void shouldCreateLogInWithClientCredentialsGrantRequestWithoutOrgWhenEmpty() throws Exception { + TokenRequest request = api.requestToken("https://myapi.auth0.com/users", " "); assertThat(request, is(notNullValue())); server.jsonResponse(AUTH_TOKENS, 200); - TokenHolder response = request.execute(); + TokenHolder response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/oauth/token")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/oauth/token")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); Map body = bodyFromRequest(recordedRequest); @@ -1134,6 +965,7 @@ public void shouldCreateLogInWithClientCredentialsGrantRequest() throws Exceptio assertThat(body, hasEntry("client_id", CLIENT_ID)); assertThat(body, hasEntry("client_secret", CLIENT_SECRET)); assertThat(body, hasEntry("audience", "https://myapi.auth0.com/users")); + assertThat(body, not(hasKey("organization"))); assertThat(response, is(notNullValue())); assertThat(response.getAccessToken(), not(emptyOrNullString())); @@ -1143,6 +975,13 @@ public void shouldCreateLogInWithClientCredentialsGrantRequest() throws Exceptio assertThat(response.getExpiresIn(), is(notNullValue())); } + @Test + public void clientCredentialsGrantRequestRequiresClientAuthentication() { + verifyThrows(IllegalStateException.class, + () -> apiNoClientAuthentication.requestToken("https://myapi.auth0.com/users"), + "A client secret or client assertion signing key is required for this operation"); + } + // Login with Passwordless @Test @@ -1151,17 +990,34 @@ public void shouldCreateStartEmailPasswordlessFlowRequest() throws Exception { PasswordlessEmailType.CODE); assertThat(request, is(notNullValue())); + emailPasswordlessRequest(request, true); + } + + @Test + public void shouldCreateStartEmailPasswordlessFlowRequestWithoutClientAuthentication() throws Exception { + Request request = apiNoClientAuthentication.startPasswordlessEmailFlow("user@domain.com", + PasswordlessEmailType.CODE); + assertThat(request, is(notNullValue())); + + emailPasswordlessRequest(request, false); + } + + private void emailPasswordlessRequest(Request request, boolean secretSent) throws Exception{ server.jsonResponse(PASSWORDLESS_EMAIL_RESPONSE, 200); - PasswordlessEmailResponse response = request.execute(); + PasswordlessEmailResponse response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/passwordless/start")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/passwordless/start")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); Map body = bodyFromRequest(recordedRequest); assertThat(body, hasEntry("connection", "email")); assertThat(body, hasEntry("client_id", CLIENT_ID)); - assertThat(body, hasEntry("client_secret", CLIENT_SECRET)); + if (secretSent) { + assertThat(body, hasEntry("client_secret", CLIENT_SECRET)); + } else { + assertThat(body, not(hasKey("client_secret"))); + } assertThat(body, hasEntry("email", "user@domain.com")); assertThat(response, is(notNullValue())); @@ -1172,16 +1028,16 @@ public void shouldCreateStartEmailPasswordlessFlowRequest() throws Exception { @Test public void startPasswordlessEmailFlowShouldThrowWhenEmailIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'email' cannot be null!"); - Request request = api.startPasswordlessEmailFlow(null, PasswordlessEmailType.CODE); + verifyThrows(IllegalArgumentException.class, + () -> api.startPasswordlessEmailFlow(null, PasswordlessEmailType.CODE), + "'email' cannot be null!"); } @Test public void startPasswordlessEmailFlowShouldThrowWhenTypeIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'type' cannot be null!"); - Request request = api.startPasswordlessEmailFlow("user@domain.com", null); + verifyThrows(IllegalArgumentException.class, + () -> api.startPasswordlessEmailFlow("user@domain.com", null), + "'type' cannot be null!"); } @Test @@ -1190,7 +1046,7 @@ public void shouldCreateStartEmailPasswordlessFlowRequestWithCustomParams() thro authParams.put("scope", "openid profile email"); authParams.put("state", "abc123"); - CustomRequest request = api.startPasswordlessEmailFlow("user@domain.com", PasswordlessEmailType.CODE) + BaseRequest request = api.startPasswordlessEmailFlow("user@domain.com", PasswordlessEmailType.CODE) .addParameter("authParams", authParams); // verify that connection parameter can be overridden for custom connection types @@ -1199,10 +1055,10 @@ public void shouldCreateStartEmailPasswordlessFlowRequestWithCustomParams() thro assertThat(request, is(notNullValue())); server.jsonResponse(PASSWORDLESS_EMAIL_RESPONSE, 200); - PasswordlessEmailResponse response = request.execute(); + PasswordlessEmailResponse response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/passwordless/start")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/passwordless/start")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); Map body = bodyFromRequest(recordedRequest); @@ -1211,6 +1067,7 @@ public void shouldCreateStartEmailPasswordlessFlowRequestWithCustomParams() thro assertThat(body, hasEntry("client_secret", CLIENT_SECRET)); assertThat(body, hasEntry("email", "user@domain.com")); assertThat(body, hasKey("authParams")); + @SuppressWarnings("unchecked") Map authParamsSent = (Map) body.get("authParams"); assertThat(authParamsSent, hasEntry("scope", authParams.get("scope"))); assertThat(authParamsSent, hasEntry("state", authParams.get("state"))); @@ -1226,17 +1083,33 @@ public void shouldCreateStartSmsPasswordlessFlowRequest() throws Exception { Request request = api.startPasswordlessSmsFlow("+16511234567"); assertThat(request, is(notNullValue())); + smsPasswordlessFlow(request, true); + } + + @Test + public void shouldCreateStartSmsPasswordlessFlowRequestWithoutClientAuthentication() throws Exception { + Request request = apiNoClientAuthentication.startPasswordlessSmsFlow("+16511234567"); + assertThat(request, is(notNullValue())); + + smsPasswordlessFlow(request, false); + } + + private void smsPasswordlessFlow(Request request, boolean secretSent) throws Exception { server.jsonResponse(PASSWORDLESS_SMS_RESPONSE, 200); - PasswordlessSmsResponse response = request.execute(); + PasswordlessSmsResponse response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/passwordless/start")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/passwordless/start")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); Map body = bodyFromRequest(recordedRequest); assertThat(body, hasEntry("connection", "sms")); assertThat(body, hasEntry("client_id", CLIENT_ID)); - assertThat(body, hasEntry("client_secret", CLIENT_SECRET)); + if (secretSent) { + assertThat(body, hasEntry("client_secret", CLIENT_SECRET)); + } else { + assertThat(body, not(hasKey("client_secret"))); + } assertThat(body, hasEntry("phone_number", "+16511234567")); assertThat(response, is(notNullValue())); @@ -1248,7 +1121,7 @@ public void shouldCreateStartSmsPasswordlessFlowRequest() throws Exception { @Test public void shouldCreateStartSmsPasswordlessFlowRequestWithCustomConnection() throws Exception { - CustomRequest request = api.startPasswordlessSmsFlow("+16511234567"); + BaseRequest request = api.startPasswordlessSmsFlow("+16511234567"); // verify that connection parameter can be overridden for custom connection types request.addParameter("connection", "custom-sms"); @@ -1256,10 +1129,10 @@ public void shouldCreateStartSmsPasswordlessFlowRequestWithCustomConnection() th assertThat(request, is(notNullValue())); server.jsonResponse(PASSWORDLESS_SMS_RESPONSE, 200); - PasswordlessSmsResponse response = request.execute(); + PasswordlessSmsResponse response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/passwordless/start")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/passwordless/start")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); Map body = bodyFromRequest(recordedRequest); @@ -1277,26 +1150,42 @@ public void shouldCreateStartSmsPasswordlessFlowRequestWithCustomConnection() th @Test public void startPasswordlessSmsFlowShouldThrowWhenPhoneIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'phoneNumber' cannot be null!"); - api.startPasswordlessSmsFlow(null); + verifyThrows(IllegalArgumentException.class, + () -> api.startPasswordlessSmsFlow(null), + "'phoneNumber' cannot be null!"); } @Test public void shouldCreateLoginWithPasswordlessCodeRequest() throws Exception { - AuthRequest request = api.exchangePasswordlessOtp("+16511234567", "email", "otp".toCharArray()); + TokenRequest request = api.exchangePasswordlessOtp("+16511234567", "email", "otp".toCharArray()); assertThat(request, is(notNullValue())); - server.jsonResponse(AUTH_TOKENS, 200); - TokenHolder response = request.execute(); - RecordedRequest recordedRequest = server.takeRequest(); + passwordlessCodeRequest(request, true); + } - assertThat(recordedRequest, hasMethodAndPath("POST", "/oauth/token")); - assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + @Test + public void shouldCreateLoginWithPasswordlessCodeRequestWithoutClientAuthentication() throws Exception { + TokenRequest request = apiNoClientAuthentication.exchangePasswordlessOtp("+16511234567", "email", "otp".toCharArray()); + assertThat(request, is(notNullValue())); + + passwordlessCodeRequest(request, false); + } + + private void passwordlessCodeRequest(TokenRequest request, boolean secretSent) throws Exception { + server.jsonResponse(AUTH_TOKENS, 200); + TokenHolder response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/oauth/token")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); Map body = bodyFromRequest(recordedRequest); assertThat(body, hasEntry("client_id", CLIENT_ID)); - assertThat(body, hasEntry("client_secret", CLIENT_SECRET)); + if (secretSent) { + assertThat(body, hasEntry("client_secret", CLIENT_SECRET)); + } else { + assertThat(body, not(hasKey("client_secret"))); + } assertThat(body, hasEntry("realm", "email")); assertThat(body, hasEntry("grant_type", "http://auth0.com/oauth/grant-type/passwordless/otp")); assertThat(body, hasEntry("otp", "otp")); @@ -1313,9 +1202,9 @@ public void shouldCreateLoginWithPasswordlessCodeRequest() throws Exception { @Test public void shouldThrowOnRevokeTokenWithNullToken() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'refresh token' cannot be null!"); - api.revokeToken(null); + verifyThrows(IllegalArgumentException.class, + () -> api.revokeToken(null), + "'refresh token' cannot be null!"); } @Test @@ -1323,16 +1212,32 @@ public void shouldCreateRevokeTokenRequest() throws Exception { Request request = api.revokeToken("2679NfkaBn62e6w5E8zNEzjr"); assertThat(request, is(notNullValue())); + revokeTokenRequest(request, true); + } + + @Test + public void shouldCreateRevokeTokenRequestWithoutClientAuthentication() throws Exception { + Request request = apiNoClientAuthentication.revokeToken("2679NfkaBn62e6w5E8zNEzjr"); + assertThat(request, is(notNullValue())); + + revokeTokenRequest(request, false); + } + + private void revokeTokenRequest( Request request, boolean secretSent) throws Exception { server.emptyResponse(200); - Void response = request.execute(); + Void response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/oauth/revoke")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/oauth/revoke")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); Map body = bodyFromRequest(recordedRequest); assertThat(body, hasEntry("client_id", CLIENT_ID)); - assertThat(body, hasEntry("client_secret", CLIENT_SECRET)); + if (secretSent) { + assertThat(body, hasEntry("client_secret", CLIENT_SECRET)); + } else { + assertThat(body, not(hasKey("client_secret"))); + } assertThat(body, hasEntry("token", "2679NfkaBn62e6w5E8zNEzjr")); assertThat(response, is(nullValue())); @@ -1343,27 +1248,43 @@ public void shouldCreateRevokeTokenRequest() throws Exception { @Test public void shouldThrowOnRenewAuthWithNullRefreshToken() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'refresh token' cannot be null!"); - api.renewAuth(null); + verifyThrows(IllegalArgumentException.class, + () -> api.renewAuth(null), + "'refresh token' cannot be null!"); + } + + @Test + public void shouldCreateRenewTokenRequest() throws Exception { + TokenRequest request = api.renewAuth("ej2E8zNEzjrcSD2edjaE"); + assertThat(request, is(notNullValue())); + + renewTokenRequest(request, true); } @Test - public void shouldCreateRenewAuthRequest() throws Exception { - AuthRequest request = api.renewAuth("ej2E8zNEzjrcSD2edjaE"); + public void shouldCreateRenewTokenRequestWithoutClientAuthentication() throws Exception { + TokenRequest request = apiNoClientAuthentication.renewAuth("ej2E8zNEzjrcSD2edjaE"); assertThat(request, is(notNullValue())); + renewTokenRequest(request, false); + } + + private void renewTokenRequest(TokenRequest request, boolean secretSent) throws Exception { server.jsonResponse(AUTH_TOKENS, 200); - TokenHolder response = request.execute(); + TokenHolder response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/oauth/token")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/oauth/token")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); Map body = bodyFromRequest(recordedRequest); assertThat(body, hasEntry("grant_type", "refresh_token")); assertThat(body, hasEntry("client_id", CLIENT_ID)); - assertThat(body, hasEntry("client_secret", CLIENT_SECRET)); + if (secretSent) { + assertThat(body, hasEntry("client_secret", CLIENT_SECRET)); + } else { + assertThat(body, not(hasKey("clieht_secret"))); + } assertThat(body, hasEntry("refresh_token", "ej2E8zNEzjrcSD2edjaE")); assertThat(response, is(notNullValue())); @@ -1374,38 +1295,91 @@ public void shouldCreateRenewAuthRequest() throws Exception { assertThat(response.getExpiresIn(), is(notNullValue())); } - // MFA grant + // PKCE + + @Test + public void shouldCreateLogInWithAuthorizationCodeGrantWithPKCERequest() throws Exception { + TokenRequest request = api.exchangeCodeWithVerifier("code123", "verifier", "https://domain.auth0.com/callback"); + assertThat(request, is(notNullValue())); + + server.jsonResponse(AUTH_TOKENS, 200); + TokenHolder response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/oauth/token")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + + Map body = bodyFromRequest(recordedRequest); + assertThat(body, hasEntry("code", "code123")); + assertThat(body, hasEntry("code_verifier", "verifier")); + assertThat(body, hasEntry("redirect_uri", "https://domain.auth0.com/callback")); + assertThat(body, hasEntry("grant_type", "authorization_code")); + assertThat(body, hasEntry("client_id", CLIENT_ID)); + assertThat(body, hasEntry("client_secret", CLIENT_SECRET)); + + assertThat(response, is(notNullValue())); + assertThat(response.getAccessToken(), not(emptyOrNullString())); + assertThat(response.getIdToken(), not(emptyOrNullString())); + assertThat(response.getRefreshToken(), not(emptyOrNullString())); + assertThat(response.getTokenType(), not(emptyOrNullString())); + assertThat(response.getExpiresIn(), is(notNullValue())); + } + + @Test + public void shouldThrowWhenVerifierNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.exchangeCodeWithVerifier("code", null,"https://domain.auth0.com/callback"), + "'verifier' cannot be null!"); + } + + // MFA @Test public void shouldThrowWhenExchangeMfaOtpCalledWithNullMfaToken() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'mfa token' cannot be null!"); - api.exchangeMfaOtp(null, new char[]{'o','t','p'}); + verifyThrows(IllegalArgumentException.class, + () -> api.exchangeMfaOtp(null, new char[]{'o','t','p'}), + "'mfa token' cannot be null!"); } @Test public void shouldThrowWhenExchangeMfaOtpCalledWithNullOtp() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'otp' cannot be null!"); - api.exchangeMfaOtp("mfaToken", null); + verifyThrows(IllegalArgumentException.class, + () -> api.exchangeMfaOtp("mfaToken", null), + "'otp' cannot be null!"); } @Test public void shouldCreateExchangeMfaOtpRequest() throws Exception { - AuthRequest request = api.exchangeMfaOtp("mfaToken", new char[]{'o','t','p'}); + TokenRequest request = api.exchangeMfaOtp("mfaToken", new char[]{'o','t','p'}); + assertThat(request, is(notNullValue())); + + mfaOtpRequest(request, true); + } + + @Test + public void shouldCreateExchangeMfaOtpRequestWithoutClientAuthentication() throws Exception { + TokenRequest request = apiNoClientAuthentication.exchangeMfaOtp("mfaToken", new char[]{'o','t','p'}); assertThat(request, is(notNullValue())); + mfaOtpRequest(request, false); + } + + private void mfaOtpRequest(TokenRequest request, boolean secretSent) throws Exception { server.jsonResponse(AUTH_TOKENS, 200); - TokenHolder response = request.execute(); + TokenHolder response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/oauth/token")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/oauth/token")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); Map body = bodyFromRequest(recordedRequest); assertThat(body, hasEntry("grant_type", "http://auth0.com/oauth/grant-type/mfa-otp")); assertThat(body, hasEntry("client_id", CLIENT_ID)); - assertThat(body, hasEntry("client_secret", CLIENT_SECRET)); + if (secretSent) { + assertThat(body, hasEntry("client_secret", CLIENT_SECRET)); + } else { + assertThat(body, not(hasKey("client_secret"))); + } assertThat(body, hasEntry("mfa_token", "mfaToken")); assertThat(body, hasEntry("otp", "otp")); @@ -1416,4 +1390,999 @@ public void shouldCreateExchangeMfaOtpRequest() throws Exception { assertThat(response.getTokenType(), not(emptyOrNullString())); assertThat(response.getExpiresIn(), is(notNullValue())); } + + @Test + public void shouldThrowWhenExchangeMfaOobCalledWithNullMfaToken() { + verifyThrows(IllegalArgumentException.class, + () -> api.exchangeMfaOob(null, new char[]{'o','t','p'}, null), + "'mfa token' cannot be null!"); + } + + @Test + public void shouldThrowWhenExchangeMfaOobCalledWithNullOoob() { + verifyThrows(IllegalArgumentException.class, + () -> api.exchangeMfaOob("mfaToken", null, null), + "'OOB code' cannot be null!"); + } + + @Test + public void shouldCreateExchangeMfaOobRequest() throws Exception { + TokenRequest request = api.exchangeMfaOob("mfaToken", new char[]{'o','o','b'}, null); + assertThat(request, is(notNullValue())); + + mfaOobExchangeRequest(request, null, true); + } + + @Test + public void shouldCreateExchangeMfaOobRequestWithoutSecret() throws Exception { + TokenRequest request = apiNoClientAuthentication.exchangeMfaOob("mfaToken", new char[]{'o','o','b'}, new char[]{'b','o','b'}); + assertThat(request, is(notNullValue())); + + mfaOobExchangeRequest(request, "bob", false); + } + + private void mfaOobExchangeRequest(TokenRequest request, String bindingCode, boolean secretSent) throws Exception { + server.jsonResponse(AUTH_TOKENS, 200); + TokenHolder response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/oauth/token")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + + Map body = bodyFromRequest(recordedRequest); + assertThat(body, hasEntry("grant_type", "http://auth0.com/oauth/grant-type/mfa-oob")); + assertThat(body, hasEntry("client_id", CLIENT_ID)); + + if (bindingCode != null) { + assertThat(body, hasEntry("binding_code", bindingCode)); + } else { + assertThat(body, not(hasKey("binding_code"))); + } + + if (secretSent) { + assertThat(body, hasEntry("client_secret", CLIENT_SECRET)); + } else { + assertThat(body, not(hasKey("client_secret"))); + } + assertThat(body, hasEntry("mfa_token", "mfaToken")); + assertThat(body, hasEntry("oob_code", "oob")); + + assertThat(response, is(notNullValue())); + assertThat(response.getAccessToken(), not(emptyOrNullString())); + assertThat(response.getIdToken(), not(emptyOrNullString())); + assertThat(response.getRefreshToken(), not(emptyOrNullString())); + assertThat(response.getTokenType(), not(emptyOrNullString())); + assertThat(response.getExpiresIn(), is(notNullValue())); + } + + @Test + public void shouldThrowWhenExchangeMfaRecoveryCodeCalledWithNullMfaToken() { + verifyThrows(IllegalArgumentException.class, + () -> api.exchangeMfaRecoveryCode(null, new char[]{'c','o','d','e'}), + "'mfa token' cannot be null!"); + } + + @Test + public void shouldThrowWhenExchangeMfaRecoveryCodeCalledWithNullCode() { + verifyThrows(IllegalArgumentException.class, + () -> api.exchangeMfaRecoveryCode("mfaToken", null), + "'recovery code' cannot be null!"); + } + + @Test + public void shouldCreateExchangeMfaRecoveryCodeRequest() throws Exception { + TokenRequest request = api.exchangeMfaRecoveryCode("mfaToken", new char[]{'c','o','d','e'}); + assertThat(request, is(notNullValue())); + + mfaRecoveryCodeExchangeRequest(request, true); + } + + @Test + public void shouldCreateExchangeMfaRecoveryCodeRequestWithoutSecret() throws Exception { + TokenRequest request = apiNoClientAuthentication.exchangeMfaRecoveryCode("mfaToken", new char[]{'c','o','d','e'}); + assertThat(request, is(notNullValue())); + + mfaRecoveryCodeExchangeRequest(request, false); + } + + private void mfaRecoveryCodeExchangeRequest(TokenRequest request, boolean secretSent) throws Exception { + server.jsonResponse(AUTH_TOKENS, 200); + TokenHolder response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/oauth/token")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + + Map body = bodyFromRequest(recordedRequest); + assertThat(body, hasEntry("grant_type", "http://auth0.com/oauth/grant-type/mfa-recovery-code")); + assertThat(body, hasEntry("client_id", CLIENT_ID)); + + if (secretSent) { + assertThat(body, hasEntry("client_secret", CLIENT_SECRET)); + } else { + assertThat(body, not(hasKey("client_secret"))); + } + assertThat(body, hasEntry("mfa_token", "mfaToken")); + assertThat(body, hasEntry("recovery_code", "code")); + + assertThat(response, is(notNullValue())); + assertThat(response.getAccessToken(), not(emptyOrNullString())); + assertThat(response.getIdToken(), not(emptyOrNullString())); + assertThat(response.getRefreshToken(), not(emptyOrNullString())); + assertThat(response.getTokenType(), not(emptyOrNullString())); + assertThat(response.getExpiresIn(), is(notNullValue())); + } + + @Test + public void addOtpAuthenticatorThrowsWhenTokenNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.addOtpAuthenticator(null), + "'mfa token' cannot be null!"); + } + + @Test + public void addOtpAuthenticatorRequest() throws Exception { + Request request = api.addOtpAuthenticator("mfaToken"); + + server.jsonResponse(AUTH_OTP_AUTHENTICATOR_RESPONSE, 200); + CreatedOtpResponse response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/mfa/associate")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + + Map body = bodyFromRequest(recordedRequest); + assertThat(body, hasEntry("authenticator_types", Collections.singletonList("otp"))); + + assertThat(response, is(notNullValue())); + assertThat(response.getAuthenticatorType(), not(emptyOrNullString())); + assertThat(response.getSecret(), not(emptyOrNullString())); + assertThat(response.getBarcodeUri(), not(emptyOrNullString())); + assertThat(response.getRecoveryCodes(), notNullValue()); + } + + @SuppressWarnings("deprecation") + @Test + public void addOobAuthenticatorDeprecatedThrowsWhenTokenNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.addOobAuthenticator(null, Collections.singletonList("auth0"), null), + "'mfa token' cannot be null!"); + } + + @SuppressWarnings("deprecation") + @Test + public void addOobAuthenticatorDeprecatedThrowsWhenChannelsNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.addOobAuthenticator("mfaToken", null, null), + "'OOB channels' cannot be null!"); + } + + @SuppressWarnings("deprecation") + @Test + public void addOobAuthenticatorDeprecatedThrowsWhenPhoneNumberNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.addOobAuthenticator("mfaToken", Collections.singletonList("sms"), null), + "'phone number' cannot be null!"); + } + + @SuppressWarnings("deprecation") + @Test + public void addOobAuthenticatorDeprecatedThrowsWhenPhoneNumberNullVoiceChannel() { + verifyThrows(IllegalArgumentException.class, + () -> api.addOobAuthenticator("mfaToken", Collections.singletonList("voice"), null), + "'phone number' cannot be null!"); + } + + @SuppressWarnings("deprecation") + @Test + public void addOobAuthenticatorDeprecatedRequest() throws Exception { + Request request = api.addOobAuthenticator("mfaToken", Collections.singletonList("sms"), "phone-number"); + + server.jsonResponse(AUTH_OOB_AUTHENTICATOR_RESPONSE, 200); + CreatedOobResponse response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/mfa/associate")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + + Map body = bodyFromRequest(recordedRequest); + assertThat(body, hasEntry("authenticator_types", Collections.singletonList("oob"))); + assertThat(body, hasEntry("oob_channels", Collections.singletonList("sms"))); + assertThat(body, hasEntry("phone_number", "phone-number")); + + assertThat(response, is(notNullValue())); + assertThat(response.getAuthenticatorType(), not(emptyOrNullString())); + assertThat(response.getOobChannel(), not(emptyOrNullString())); + assertThat(response.getOobCode(), not(emptyOrNullString())); + assertThat(response.getBarcodeUri(), not(emptyOrNullString())); + assertThat(response.getRecoveryCodes(), notNullValue()); + } + + @SuppressWarnings("deprecation") + @Test + public void addOobAuthenticatorDeprecatedRequestWithNoPhoneNumber() throws Exception { + Request request = api.addOobAuthenticator("mfaToken", Collections.singletonList("auth0"), null); + + server.jsonResponse(AUTH_OOB_AUTHENTICATOR_RESPONSE, 200); + CreatedOobResponse response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/mfa/associate")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + + Map body = bodyFromRequest(recordedRequest); + assertThat(body, hasEntry("authenticator_types", Collections.singletonList("oob"))); + assertThat(body, hasEntry("oob_channels", Collections.singletonList("auth0"))); + + assertThat(response, is(notNullValue())); + assertThat(response.getAuthenticatorType(), not(emptyOrNullString())); + assertThat(response.getOobChannel(), not(emptyOrNullString())); + assertThat(response.getOobCode(), not(emptyOrNullString())); + assertThat(response.getBarcodeUri(), not(emptyOrNullString())); + assertThat(response.getRecoveryCodes(), notNullValue()); + } + + @Test + public void addOobAuthenticatorThrowsWhenTokenNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.addOobAuthenticator(null, Collections.singletonList("auth0"), null, null), + "'mfa token' cannot be null!"); + } + + + @Test + public void addOobAuthenticatorThrowsWhenChannelsNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.addOobAuthenticator("mfaToken", null, null, null), + "'OOB channels' cannot be null!"); + } + + @Test + public void addOobAuthenticatorThrowsWhenChannelsNullWithPhoneNumber() { + verifyThrows(IllegalArgumentException.class, + () -> api.addOobAuthenticator("mfaToken", null, "phone-number", null), + "'OOB channels' cannot be null!"); + } + + @Test + public void addOobAuthenticatorThrowsWhenChannelsNullWithEmail() { + verifyThrows(IllegalArgumentException.class, + () -> api.addOobAuthenticator("mfaToken", null, null, "email-address"), + "'OOB channels' cannot be null!"); + } + + @Test + public void addOobAuthenticatorThrowsWhenPhoneNumberNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.addOobAuthenticator("mfaToken", Collections.singletonList("sms"), null, null), + "'phone number' cannot be null!"); + } + + @Test + public void addOobAuthenticatorThrowsWhenPhoneNumberNullWithVoiceChannel() { + verifyThrows(IllegalArgumentException.class, + () -> api.addOobAuthenticator("mfaToken", Collections.singletonList("voice"), null, null), + "'phone number' cannot be null!"); + } + + @Test + public void addOobAuthenticatorThrowsWhenEmailNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.addOobAuthenticator("mfaToken", Collections.singletonList("email"), null, null), + "'email address' cannot be null!"); + } + + @Test + public void addOobAuthenticatorRequestWithPhoneNumber() throws Exception { + Request request = api.addOobAuthenticator("mfaToken", Collections.singletonList("sms"), "phone-number", null); + + server.jsonResponse(AUTH_OOB_AUTHENTICATOR_RESPONSE, 200); + CreatedOobResponse response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/mfa/associate")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + + Map body = bodyFromRequest(recordedRequest); + assertThat(body, hasEntry("authenticator_types", Collections.singletonList("oob"))); + assertThat(body, hasEntry("oob_channels", Collections.singletonList("sms"))); + assertThat(body, hasEntry("phone_number", "phone-number")); + + assertThat(response, is(notNullValue())); + assertThat(response.getAuthenticatorType(), not(emptyOrNullString())); + assertThat(response.getOobChannel(), not(emptyOrNullString())); + assertThat(response.getOobCode(), not(emptyOrNullString())); + assertThat(response.getBarcodeUri(), not(emptyOrNullString())); + assertThat(response.getRecoveryCodes(), notNullValue()); + } + + @Test + public void addOobAuthenticatorRequestWithEmail() throws Exception { + Request request = api.addOobAuthenticator("mfaToken", Collections.singletonList("email"), null, "email-address"); + + server.jsonResponse(AUTH_OOB_AUTHENTICATOR_RESPONSE, 200); + CreatedOobResponse response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/mfa/associate")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + + Map body = bodyFromRequest(recordedRequest); + assertThat(body, hasEntry("authenticator_types", Collections.singletonList("oob"))); + assertThat(body, hasEntry("oob_channels", Collections.singletonList("email"))); + assertThat(body, hasEntry("email", "email-address")); + + assertThat(response, is(notNullValue())); + assertThat(response.getAuthenticatorType(), not(emptyOrNullString())); + assertThat(response.getOobChannel(), not(emptyOrNullString())); + assertThat(response.getOobCode(), not(emptyOrNullString())); + assertThat(response.getBarcodeUri(), not(emptyOrNullString())); + assertThat(response.getRecoveryCodes(), notNullValue()); + } + + @Test + public void addOobAuthenticatorRequestWithNoContactInfo() throws Exception { + Request request = api.addOobAuthenticator("mfaToken", Collections.singletonList("auth0"), null, null); + + server.jsonResponse(AUTH_OOB_AUTHENTICATOR_RESPONSE, 200); + CreatedOobResponse response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/mfa/associate")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + + Map body = bodyFromRequest(recordedRequest); + assertThat(body, hasEntry("authenticator_types", Collections.singletonList("oob"))); + assertThat(body, hasEntry("oob_channels", Collections.singletonList("auth0"))); + + assertThat(response, is(notNullValue())); + assertThat(response.getAuthenticatorType(), not(emptyOrNullString())); + assertThat(response.getOobChannel(), not(emptyOrNullString())); + assertThat(response.getOobCode(), not(emptyOrNullString())); + assertThat(response.getBarcodeUri(), not(emptyOrNullString())); + assertThat(response.getRecoveryCodes(), notNullValue()); + } + + @Test + public void addOobAuthenticatorRequestWithMultipleChannels() throws Exception { + Request request = api.addOobAuthenticator("mfaToken", Arrays.asList("sms", "email", "auth0"), "phone-number", "email-address"); + + server.jsonResponse(AUTH_OOB_AUTHENTICATOR_RESPONSE, 200); + CreatedOobResponse response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/mfa/associate")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + + Map body = bodyFromRequest(recordedRequest); + assertThat(body, hasEntry("authenticator_types", Collections.singletonList("oob"))); + assertThat(body, hasEntry("oob_channels", Arrays.asList("sms", "email", "auth0"))); + assertThat(body, hasEntry("phone_number", "phone-number")); + assertThat(body, hasEntry("email", "email-address")); + + assertThat(response, is(notNullValue())); + assertThat(response.getAuthenticatorType(), not(emptyOrNullString())); + assertThat(response.getOobChannel(), not(emptyOrNullString())); + assertThat(response.getOobCode(), not(emptyOrNullString())); + assertThat(response.getBarcodeUri(), not(emptyOrNullString())); + assertThat(response.getRecoveryCodes(), notNullValue()); + } + + @Test + public void addOobAuthenticatorRequestWithAuth0Channel() throws Exception { + Request request = api.addOobAuthenticator("mfaToken", Collections.singletonList("auth0"), null, "email-address"); + + server.jsonResponse(AUTH_OOB_AUTHENTICATOR_RESPONSE, 200); + CreatedOobResponse response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/mfa/associate")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + + Map body = bodyFromRequest(recordedRequest); + assertThat(body, hasEntry("authenticator_types", Collections.singletonList("oob"))); + assertThat(body, hasEntry("oob_channels", Collections.singletonList("auth0"))); + + assertThat(response, is(notNullValue())); + assertThat(response.getAuthenticatorType(), not(emptyOrNullString())); + assertThat(response.getOobChannel(), not(emptyOrNullString())); + assertThat(response.getOobCode(), not(emptyOrNullString())); + assertThat(response.getBarcodeUri(), not(emptyOrNullString())); + assertThat(response.getRecoveryCodes(), notNullValue()); + } + + @Test + public void listAuthenticatorsThrowsWhenTokenNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.listAuthenticators(null), + "'access token' cannot be null!"); + } + + @Test + public void listAuthenticatorsRequest() throws Exception { + Request> request = api.listAuthenticators("token"); + + server.jsonResponse(AUTH_LIST_AUTHENTICATORS_RESPONSE, 200); + List response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/mfa/authenticators")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer token")); + + assertThat(response, is(notNullValue())); + } + + @Test + public void deleteAuthenticatorThrowsWhenTokenNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.deleteAuthenticator(null, "authenticatorId"), + "'access token' cannot be null!"); + } + + @Test + public void deleteAuthenticatorThrowsWhenAuthenticatorIdNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.deleteAuthenticator("Bearer accessToken", null), + "'authenticator id' cannot be null!"); + } + + @Test + public void deleteAuthenticatorRequest() throws Exception { + Request request = api.deleteAuthenticator("accessToken", "authenticatorId"); + + server.jsonResponse(AUTH_LIST_AUTHENTICATORS_RESPONSE, 200); + Void response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/mfa/authenticators/authenticatorId")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer accessToken")); + + assertThat(response, is(nullValue())); + } + + @Test + public void challengeRequestThrowsWhenTokenNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.mfaChallengeRequest(null, "otp", "authenticatorId"), + "'mfa token' cannot be null!"); + } + + @Test + public void challengeRequest() throws Exception { + Request request = api.mfaChallengeRequest("mfaToken", "otp", "authenticatorId"); + + server.jsonResponse(AUTH_CHALLENGE_RESPONSE, 200); + MfaChallengeResponse response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/mfa/challenge")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + + Map body = bodyFromRequest(recordedRequest); + assertThat(body, hasEntry("mfa_token", "mfaToken")); + assertThat(body, hasEntry("client_id", CLIENT_ID)); + assertThat(body, hasEntry("client_secret", CLIENT_SECRET)); + assertThat(body, hasEntry("challenge_type", "otp")); + assertThat(body, hasEntry("authenticator_id", "authenticatorId")); + + assertThat(response, is(notNullValue())); + assertThat(response.getChallengeType(), not(emptyOrNullString())); + assertThat(response.getBindingMethod(), not(emptyOrNullString())); + assertThat(response.getOobCode(), not(emptyOrNullString())); + } + + // Client Assertion tests + @Test + public void shouldAddAndPreferClientAuthentication() throws Exception { + AuthAPI authAPI = AuthAPI.newBuilder(server.getBaseUrl(), CLIENT_ID, CLIENT_SECRET) + .withClientAssertionSigner(new TestAssertionSigner("token")) + .build(); + TokenRequest request = authAPI.exchangeCode("code123", "https://domain.auth0.com/callback"); + assertThat(request, is(notNullValue())); + + server.jsonResponse(AUTH_TOKENS, 200); + TokenHolder response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/oauth/token")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + + Map body = bodyFromRequest(recordedRequest); + assertThat(body, hasEntry("code", "code123")); + assertThat(body, hasEntry("redirect_uri", "https://domain.auth0.com/callback")); + assertThat(body, hasEntry("grant_type", "authorization_code")); + assertThat(body, hasEntry("client_id", CLIENT_ID)); + assertThat(body, not(hasEntry("client_secret", CLIENT_SECRET))); + assertThat(body, hasEntry("client_assertion", "token")); + assertThat(body, hasEntry("client_assertion_type", "urn:ietf:params:oauth:client-assertion-type:jwt-bearer")); + + assertThat(response, is(notNullValue())); + assertThat(response.getAccessToken(), not(emptyOrNullString())); + assertThat(response.getIdToken(), not(emptyOrNullString())); + assertThat(response.getRefreshToken(), not(emptyOrNullString())); + assertThat(response.getTokenType(), not(emptyOrNullString())); + assertThat(response.getExpiresIn(), is(notNullValue())); + } + + @Test + public void shouldNotAddAnyParamsIfNoSecretOrAssertion() throws Exception { + AuthAPI authAPI = AuthAPI.newBuilder(server.getBaseUrl(), CLIENT_ID).build(); + TokenRequest request = authAPI.exchangeCodeWithVerifier("code123", "verifier", "https://domain.auth0.com/callback"); + + assertThat(request, is(notNullValue())); + + server.jsonResponse(AUTH_TOKENS, 200); + TokenHolder response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/oauth/token")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + + Map body = bodyFromRequest(recordedRequest); + assertThat(body, hasEntry("code", "code123")); + assertThat(body, hasEntry("code_verifier", "verifier")); + assertThat(body, hasEntry("redirect_uri", "https://domain.auth0.com/callback")); + assertThat(body, hasEntry("grant_type", "authorization_code")); + assertThat(body, hasEntry("client_id", CLIENT_ID)); + assertThat(body, not(hasEntry("client_secret", CLIENT_SECRET))); + assertThat(body, not(hasEntry("client_assertion", "token"))); + assertThat(body, not(hasEntry("client_assertion_type", "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"))); + + assertThat(response, is(notNullValue())); + assertThat(response.getAccessToken(), not(emptyOrNullString())); + assertThat(response.getIdToken(), not(emptyOrNullString())); + assertThat(response.getRefreshToken(), not(emptyOrNullString())); + assertThat(response.getTokenType(), not(emptyOrNullString())); + assertThat(response.getExpiresIn(), is(notNullValue())); + } + + @Test + public void authorizeUrlWithPARShouldThrowWhenRequestUriNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.authorizeUrlWithPAR(null), + "'request uri' cannot be null!"); + } + + @Test + public void shouldBuildAuthorizeUrlWithPAR() { + AuthAPI api = AuthAPI.newBuilder("domain.auth0.com", CLIENT_ID, CLIENT_SECRET).build(); + String url = api.authorizeUrlWithPAR("urn:example:bwc4JK-ESC0w8acc191e-Y1LTC2"); + assertThat(url, is(notNullValue())); + assertThat(url, isUrl("https", "domain.auth0.com", "/authorize")); + + assertThat(url, hasQueryParameter("request_uri", "urn:example:bwc4JK-ESC0w8acc191e-Y1LTC2")); + assertThat(url, hasQueryParameter("client_id", CLIENT_ID)); + } + + @Test + public void pushedAuthorizationRequestShouldThrowWhenRedirectUriIsNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.pushedAuthorizationRequest(null, "code", Collections.emptyMap()), + "'redirect uri' must be a valid URL!"); + } + + @Test + public void pushedAuthorizationRequestShouldThrowWhenResponseTypeIsNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.pushedAuthorizationRequest("https://domain.com/callback", null, Collections.emptyMap()), + "'response type' cannot be null!"); + } + + @Test + public void shouldCreatePushedAuthorizationRequestWithNullAdditionalParams() throws Exception { + Request request = api.pushedAuthorizationRequest("https://domain.com/callback", "code", null); + assertThat(request, is(notNullValue())); + + server.jsonResponse(PUSHED_AUTHORIZATION_RESPONSE, 200); + PushedAuthorizationResponse response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/oauth/par")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/x-www-form-urlencoded")); + + String body = readFromRequest(recordedRequest); + assertThat(body, containsString("client_id=" + CLIENT_ID)); + assertThat(body, containsString("redirect_uri=" + "https%3A%2F%2Fround-lake.dustinice.workers.dev%3A443%2Fhttps%2Fdomain.com%2Fcallback")); + assertThat(body, containsString("response_type=" + "code")); + assertThat(body, containsString("client_secret=" + CLIENT_SECRET)); + + assertThat(response, is(notNullValue())); + assertThat(response.getRequestURI(), not(emptyOrNullString())); + assertThat(response.getExpiresIn(), notNullValue()); + } + + @Test + public void shouldCreatePushedAuthorizationRequestWithAdditionalParams() throws Exception { + Map additionalParams = new HashMap<>(); + additionalParams.put("audience", "aud"); + additionalParams.put("connection", "conn"); + Request request = api.pushedAuthorizationRequest("https://domain.com/callback", "code", additionalParams); + assertThat(request, is(notNullValue())); + + server.jsonResponse(PUSHED_AUTHORIZATION_RESPONSE, 200); + PushedAuthorizationResponse response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/oauth/par")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/x-www-form-urlencoded")); + + String body = readFromRequest(recordedRequest); + assertThat(body, containsString("client_id=" + CLIENT_ID)); + assertThat(body, containsString("redirect_uri=" + "https%3A%2F%2Fround-lake.dustinice.workers.dev%3A443%2Fhttps%2Fdomain.com%2Fcallback")); + assertThat(body, containsString("response_type=" + "code")); + assertThat(body, containsString("client_secret=" + CLIENT_SECRET)); + assertThat(body, containsString("audience=" + "aud")); + assertThat(body, containsString("connection=" + "conn")); + + assertThat(response, is(notNullValue())); + assertThat(response.getRequestURI(), not(emptyOrNullString())); + assertThat(response.getExpiresIn(), notNullValue()); + } + + @Test + @SuppressWarnings("unchecked") + public void shouldCreatePushedAuthorizationRequestWithAuthDetails() throws Exception { + Map authorizationDetails = new HashMap<>(); + authorizationDetails.put("type", "account information"); + authorizationDetails.put("locations", Collections.singletonList("https://example.com/customers")); + authorizationDetails.put("actions", Arrays.asList("read", "write")); + List> authDetailsList = Collections.singletonList(authorizationDetails); + + Request request = api.pushedAuthorizationRequest("https://domain.com/callback", "code", null, authDetailsList); + assertThat(request, is(notNullValue())); + + server.jsonResponse(PUSHED_AUTHORIZATION_RESPONSE, 200); + PushedAuthorizationResponse response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/oauth/par")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/x-www-form-urlencoded")); + + String body = readFromRequest(recordedRequest); + assertThat(body, containsString("client_id=" + CLIENT_ID)); + assertThat(body, containsString("redirect_uri=" + "https%3A%2F%2Fround-lake.dustinice.workers.dev%3A443%2Fhttps%2Fdomain.com%2Fcallback")); + assertThat(body, containsString("response_type=" + "code")); + assertThat(body, containsString("client_secret=" + CLIENT_SECRET)); + + String authDetailsParam = getQueryMap(body).get("authorization_details"); + String decodedAuthDetails = URLDecoder.decode(authDetailsParam, StandardCharsets.UTF_8.name()); + TypeReference>> typeReference = new TypeReference>>() { + }; + List> deserialized = ObjectMapperProvider.getMapper().readValue(decodedAuthDetails, typeReference); + assertThat(deserialized, notNullValue()); + assertThat(deserialized, hasSize(1)); + assertThat(deserialized.get(0).get("type"), is("account information")); + + List locations = (List) deserialized.get(0).get("locations"); + List actions = (List) deserialized.get(0).get("actions"); + + assertThat(locations, hasSize(1)); + assertThat(locations.get(0), is("https://example.com/customers")); + assertThat(actions, hasSize(2)); + assertThat(actions, contains("read", "write")); + + assertThat(response, is(notNullValue())); + assertThat(response.getRequestURI(), not(emptyOrNullString())); + assertThat(response.getExpiresIn(), notNullValue()); + } + + @Test + public void shouldThrowWhenCreatePushedAuthorizationRequestWithInvalidAuthDetails() { + // force Jackson to throw error on serialization + // see https://stackoverflow.com/questions/26716020/how-to-get-a-jsonprocessingexception-using-jackson + @SuppressWarnings("unchecked") + List> mockList = mock(List.class); + when(mockList.toString()).thenReturn(mockList.getClass().getName()); + + IllegalArgumentException e = verifyThrows(IllegalArgumentException.class, + () -> api.pushedAuthorizationRequest("https://domain.com/callback", "code", null, mockList)); + + assertThat(e.getMessage(), is("'authorizationDetails' must be a list that can be serialized to JSON")); + assertThat(e.getCause(), instanceOf(JsonProcessingException.class)); + } + + @Test + public void shouldCreatePushedAuthorizationRequestWithoutSecret() throws Exception { + AuthAPI api = AuthAPI.newBuilder(server.getBaseUrl(), CLIENT_ID).build(); + Request request = api.pushedAuthorizationRequest("https://domain.com/callback", "code", null); + assertThat(request, is(notNullValue())); + + server.jsonResponse(PUSHED_AUTHORIZATION_RESPONSE, 200); + PushedAuthorizationResponse response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/oauth/par")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/x-www-form-urlencoded")); + + String body = readFromRequest(recordedRequest); + assertThat(body, containsString("client_id=" + CLIENT_ID)); + assertThat(body, containsString("redirect_uri=" + "https%3A%2F%2Fround-lake.dustinice.workers.dev%3A443%2Fhttps%2Fdomain.com%2Fcallback")); + assertThat(body, containsString("response_type=" + "code")); + assertThat(body, not(containsString("client_secret"))); + + assertThat(response, is(notNullValue())); + assertThat(response.getRequestURI(), not(emptyOrNullString())); + assertThat(response.getExpiresIn(), notNullValue()); + } + + @Test + public void authorizeUrlWithJARShouldThrowWhenRequestNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.authorizeUrlWithJAR(null), + "'request' cannot be null!"); + } + + @Test + public void shouldBuildAuthorizeUrlWithJAR() { + String requestJwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGllbnRfaWQiOiIxMjM0NTYiLCJyZWRpcmVjdF91cmkiOiJodHRwOi8vbG9jYWxob3N0OjMwMDAiLCJyZXNwb25zZV90eXBlIjoiY29kZSIsIm5vbmNlIjoiMTIzNCIsInN0YXRlIjoiNzhkeXVma2poZGYifQ.UQDz8hBIabaqatY75BvqGyiPoOqNYJQIsimUKg4_VrU"; + AuthAPI api = AuthAPI.newBuilder("domain.auth0.com", CLIENT_ID, CLIENT_SECRET).build(); + String url = api.authorizeUrlWithJAR("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGllbnRfaWQiOiIxMjM0NTYiLCJyZWRpcmVjdF91cmkiOiJodHRwOi8vbG9jYWxob3N0OjMwMDAiLCJyZXNwb25zZV90eXBlIjoiY29kZSIsIm5vbmNlIjoiMTIzNCIsInN0YXRlIjoiNzhkeXVma2poZGYifQ.UQDz8hBIabaqatY75BvqGyiPoOqNYJQIsimUKg4_VrU"); + assertThat(url, is(notNullValue())); + assertThat(url, isUrl("https", "domain.auth0.com", "/authorize")); + + assertThat(url, hasQueryParameter("request", requestJwt)); + assertThat(url, hasQueryParameter("client_id", CLIENT_ID)); + } + + @Test + public void pushedAuthorizationRequestShouldThrowWhenRequestIsNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.pushedAuthorizationRequestWithJAR(null), + "'request' cannot be null!"); + } + + @Test + public void shouldCreatePushedAuthorizationJarRequest() throws Exception { + String requestJwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGllbnRfaWQiOiIxMjM0NTYiLCJyZWRpcmVjdF91cmkiOiJodHRwOi8vbG9jYWxob3N0OjMwMDAiLCJyZXNwb25zZV90eXBlIjoiY29kZSIsIm5vbmNlIjoiMTIzNCIsInN0YXRlIjoiNzhkeXVma2poZGYifQ.UQDz8hBIabaqatY75BvqGyiPoOqNYJQIsimUKg4_VrU"; + Request request = api.pushedAuthorizationRequestWithJAR(requestJwt); + assertThat(request, is(notNullValue())); + + server.jsonResponse(PUSHED_AUTHORIZATION_RESPONSE, 200); + PushedAuthorizationResponse response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/oauth/par")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/x-www-form-urlencoded")); + + String body = readFromRequest(recordedRequest); + assertThat(body, containsString("client_id=" + CLIENT_ID)); + assertThat(body, containsString("request=" + requestJwt)); + assertThat(body, containsString("client_secret=" + CLIENT_SECRET)); + + assertThat(response, is(notNullValue())); + assertThat(response.getRequestURI(), not(emptyOrNullString())); + assertThat(response.getExpiresIn(), notNullValue()); + } + + @Test + public void shouldCreatePushedAuthorizationJarRequestWithoutSecret() throws Exception { + String requestJwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGllbnRfaWQiOiIxMjM0NTYiLCJyZWRpcmVjdF91cmkiOiJodHRwOi8vbG9jYWxob3N0OjMwMDAiLCJyZXNwb25zZV90eXBlIjoiY29kZSIsIm5vbmNlIjoiMTIzNCIsInN0YXRlIjoiNzhkeXVma2poZGYifQ.UQDz8hBIabaqatY75BvqGyiPoOqNYJQIsimUKg4_VrU"; + AuthAPI api = AuthAPI.newBuilder(server.getBaseUrl(), CLIENT_ID).build(); + Request request = api.pushedAuthorizationRequestWithJAR(requestJwt); + assertThat(request, is(notNullValue())); + + server.jsonResponse(PUSHED_AUTHORIZATION_RESPONSE, 200); + PushedAuthorizationResponse response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/oauth/par")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/x-www-form-urlencoded")); + + String body = readFromRequest(recordedRequest); + assertThat(body, containsString("client_id=" + CLIENT_ID)); + assertThat(body, containsString("request=" + requestJwt)); + assertThat(body, not(containsString("client_secret"))); + + assertThat(response, is(notNullValue())); + assertThat(response.getRequestURI(), not(emptyOrNullString())); + assertThat(response.getExpiresIn(), notNullValue()); + } + + @Test + @SuppressWarnings("unchecked") + public void shouldCreatePushedAuthorizationJarRequestWithoutAuthDetails() throws Exception { + String requestJwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGllbnRfaWQiOiIxMjM0NTYiLCJyZWRpcmVjdF91cmkiOiJodHRwOi8vbG9jYWxob3N0OjMwMDAiLCJyZXNwb25zZV90eXBlIjoiY29kZSIsIm5vbmNlIjoiMTIzNCIsInN0YXRlIjoiNzhkeXVma2poZGYifQ.UQDz8hBIabaqatY75BvqGyiPoOqNYJQIsimUKg4_VrU"; + Map authorizationDetails = new HashMap<>(); + authorizationDetails.put("type", "account information"); + authorizationDetails.put("locations", Collections.singletonList("https://example.com/customers")); + authorizationDetails.put("actions", Arrays.asList("read", "write")); + List> authDetailsList = Collections.singletonList(authorizationDetails); + + Request request = api.pushedAuthorizationRequestWithJAR(requestJwt, authDetailsList); + assertThat(request, is(notNullValue())); + + server.jsonResponse(PUSHED_AUTHORIZATION_RESPONSE, 200); + PushedAuthorizationResponse response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/oauth/par")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/x-www-form-urlencoded")); + + String body = readFromRequest(recordedRequest); + assertThat(body, containsString("client_id=" + CLIENT_ID)); + assertThat(body, containsString("request=" + requestJwt)); + assertThat(body, containsString("client_secret=" + CLIENT_SECRET)); + + String authDetailsParam = getQueryMap(body).get("authorization_details"); + String decodedAuthDetails = URLDecoder.decode(authDetailsParam, StandardCharsets.UTF_8.name()); + TypeReference>> typeReference = new TypeReference>>() { + }; + List> deserialized = ObjectMapperProvider.getMapper().readValue(decodedAuthDetails, typeReference); + assertThat(deserialized, notNullValue()); + assertThat(deserialized, hasSize(1)); + assertThat(deserialized.get(0).get("type"), is("account information")); + + List locations = (List) deserialized.get(0).get("locations"); + List actions = (List) deserialized.get(0).get("actions"); + + assertThat(locations, hasSize(1)); + assertThat(locations.get(0), is("https://example.com/customers")); + assertThat(actions, hasSize(2)); + assertThat(actions, contains("read", "write")); + + assertThat(response, is(notNullValue())); + assertThat(response.getRequestURI(), not(emptyOrNullString())); + assertThat(response.getExpiresIn(), notNullValue()); + } + + @Test + @SuppressWarnings("unchecked") + public void shouldThrowWhenCreatePushedAuthorizationJarRequestWithInvalidAuthDetails() { + String requestJwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGllbnRfaWQiOiIxMjM0NTYiLCJyZWRpcmVjdF91cmkiOiJodHRwOi8vbG9jYWxob3N0OjMwMDAiLCJyZXNwb25zZV90eXBlIjoiY29kZSIsIm5vbmNlIjoiMTIzNCIsInN0YXRlIjoiNzhkeXVma2poZGYifQ.UQDz8hBIabaqatY75BvqGyiPoOqNYJQIsimUKg4_VrU"; + // force Jackson to throw error on serialization + // see https://stackoverflow.com/questions/26716020/how-to-get-a-jsonprocessingexception-using-jackson + List mockList = mock(List.class); + when(mockList.toString()).thenReturn(mockList.getClass().getName()); + + IllegalArgumentException e = verifyThrows(IllegalArgumentException.class, + () -> api.pushedAuthorizationRequestWithJAR(requestJwt, mockList)); + + assertThat(e.getMessage(), is("'authorizationDetails' must be a list that can be serialized to JSON")); + assertThat(e.getCause(), instanceOf(JsonProcessingException.class)); + } + + @Test + public void authorizeBackChannelWhenScopeIsNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.authorizeBackChannel(null, "This is binding message", getLoginHint()), + "'scope' cannot be null!"); + } + + @Test + public void authorizeBackChannelWhenBindingMessageIsNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.authorizeBackChannel("openid", null, getLoginHint()), + "'binding message' cannot be null!"); + } + + @Test + public void authorizeBackChannelWhenLoginHintIsNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.authorizeBackChannel("openid", "This is binding message", null), + "'login hint' cannot be null!"); + } + + @Test + public void authorizeBackChannel() throws Exception { + Request request = api.authorizeBackChannel("openid", "This is binding message", getLoginHint()); + assertThat(request, is(notNullValue())); + + server.jsonResponse(BACK_CHANNEL_AUTHORIZE_RESPONSE, 200); + BackChannelAuthorizeResponse response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/bc-authorize")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/x-www-form-urlencoded")); + + String body = URLDecoder.decode(readFromRequest(recordedRequest), StandardCharsets.UTF_8.name()); + assertThat(body, containsString("scope=" + "openid")); + assertThat(body, containsString("client_id=" + CLIENT_ID)); + assertThat(body, containsString("client_secret=" + CLIENT_SECRET)); + assertThat(body, containsString("binding_message=This is binding message")); + assertThat(body, containsString("login_hint={\"sub\":\"auth0|user1\",\"format\":\"format1\",\"iss\":\"https://auth0.com\"}")); + + assertThat(response, is(notNullValue())); + assertThat(response.getAuthReqId(), not(emptyOrNullString())); + assertThat(response.getExpiresIn(), notNullValue()); + assertThat(response.getInterval(), notNullValue()); + } + + @Test + public void authorizeBackChannelWithAudienceAndRequestedExpiry() throws Exception { + Request request = api.authorizeBackChannel("openid", "This is binding message", getLoginHint(), "https://api.example.com", 300); + assertThat(request, is(notNullValue())); + + server.jsonResponse(BACK_CHANNEL_AUTHORIZE_RESPONSE, 200); + BackChannelAuthorizeResponse response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/bc-authorize")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/x-www-form-urlencoded")); + + String body = URLDecoder.decode(readFromRequest(recordedRequest), StandardCharsets.UTF_8.name()); + assertThat(body, containsString("scope=" + "openid")); + assertThat(body, containsString("client_id=" + CLIENT_ID)); + assertThat(body, containsString("client_secret=" + CLIENT_SECRET)); + assertThat(body, containsString("binding_message=This is binding message")); + assertThat(body, containsString("login_hint={\"sub\":\"auth0|user1\",\"format\":\"format1\",\"iss\":\"https://auth0.com\"}")); + assertThat(body, containsString("requested_expiry=" + 300)); + assertThat(body, containsString("audience=" + "https://api.example.com")); + + assertThat(response, is(notNullValue())); + assertThat(response.getAuthReqId(), not(emptyOrNullString())); + assertThat(response.getExpiresIn(), notNullValue()); + assertThat(response.getInterval(), notNullValue()); + } + + private Map getLoginHint() { + Map loginHint = new HashMap<>(); + loginHint.put("format", "format1"); + loginHint.put("iss", "https://auth0.com"); + loginHint.put("sub", "auth0|user1"); + return loginHint; + } + + @Test + public void getBackChannelLoginStatusWhenAuthReqIdIsNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.getBackChannelLoginStatus(null, "ciba"), + "'auth req id' cannot be null!"); + } + + @Test + public void getBackChannelLoginStatusWhenGrantTypeIsNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.getBackChannelLoginStatus("red_id_1", null), + "'grant type' cannot be null!"); + } + + @Test + public void getBackChannelLoginStatus() throws Exception { + Request request = api.getBackChannelLoginStatus("red_id_1", "ciba"); + assertThat(request, is(notNullValue())); + + server.jsonResponse(BACK_CHANNEL_LOGIN_STATUS_RESPONSE, 200); + BackChannelTokenResponse response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/oauth/token")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/x-www-form-urlencoded")); + + String body = URLDecoder.decode(readFromRequest(recordedRequest), StandardCharsets.UTF_8.name()); + assertThat(body, containsString("client_id=" + CLIENT_ID)); + assertThat(body, containsString("client_secret=" + CLIENT_SECRET)); + assertThat(body, containsString("auth_req_id=red_id_1")); + assertThat(body, containsString("grant_type=ciba")); + + assertThat(response, is(notNullValue())); + assertThat(response.getAccessToken(), not(emptyOrNullString())); + assertThat(response.getIdToken(), not(emptyOrNullString())); + assertThat(response.getExpiresIn(), notNullValue()); + assertThat(response.getScope(), not(emptyOrNullString())); + } + + + private Map getQueryMap(String input) { + String[] params = input.split("&"); + + return Arrays.stream(params) + .map(param -> param.split("=")) + .collect(Collectors.toMap(p -> p[0], p -> p[1])); + } + + static class TestAssertionSigner implements ClientAssertionSigner { + + private final String token; + + public TestAssertionSigner(String token) { + this.token = token; + } + + @Override + public String createSignedClientAssertion(String issuer, String audience, String subject) { + return token; + } + } } diff --git a/src/test/java/com/auth0/client/auth/AuthorizeUrlBuilderTest.java b/src/test/java/com/auth0/client/auth/AuthorizeUrlBuilderTest.java index 2e9b5ac76..966d54572 100644 --- a/src/test/java/com/auth0/client/auth/AuthorizeUrlBuilderTest.java +++ b/src/test/java/com/auth0/client/auth/AuthorizeUrlBuilderTest.java @@ -1,12 +1,11 @@ package com.auth0.client.auth; import okhttp3.HttpUrl; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; +import org.junit.jupiter.api.Test; import java.net.URLEncoder; +import static com.auth0.AssertsUtil.verifyThrows; import static com.auth0.client.UrlMatcher.*; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; @@ -18,29 +17,25 @@ public class AuthorizeUrlBuilderTest { private static final String CLIENT_ID = "clientId"; private static final String REDIRECT_URI = "https://domain.auth0.com/callback"; - @SuppressWarnings("deprecation") - @Rule - public ExpectedException exception = ExpectedException.none(); - @Test public void shouldThrowWhenBaseUrlIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'base url' cannot be null!"); - AuthorizeUrlBuilder.newInstance(null, CLIENT_ID, REDIRECT_URI); + verifyThrows(IllegalArgumentException.class, + () -> AuthorizeUrlBuilder.newInstance(null, CLIENT_ID, REDIRECT_URI), + "'base url' cannot be null!"); } @Test public void shouldThrowWhenRedirectUriIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'redirect uri' cannot be null!"); - AuthorizeUrlBuilder.newInstance(DOMAIN, CLIENT_ID, null); + verifyThrows(IllegalArgumentException.class, + () -> AuthorizeUrlBuilder.newInstance(DOMAIN, CLIENT_ID, null), + "'redirect uri' cannot be null!"); } @Test public void shouldThrowWhenClientIdIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'client id' cannot be null!"); - AuthorizeUrlBuilder.newInstance(DOMAIN, null, REDIRECT_URI); + verifyThrows(IllegalArgumentException.class, + () -> AuthorizeUrlBuilder.newInstance(DOMAIN, null, REDIRECT_URI), + "'client id' cannot be null!"); } @Test @@ -99,10 +94,10 @@ public void shouldSetConnection() { @Test public void shouldThrowWhenConnectionIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'connection' cannot be null!"); - AuthorizeUrlBuilder.newInstance(DOMAIN, CLIENT_ID, REDIRECT_URI) - .withConnection(null); + verifyThrows(IllegalArgumentException.class, + () -> AuthorizeUrlBuilder.newInstance(DOMAIN, CLIENT_ID, REDIRECT_URI) + .withConnection(null), + "'connection' cannot be null!"); } @Test @@ -115,10 +110,10 @@ public void shouldSetAudience() { @Test public void shouldThrowWhenAudienceIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'audience' cannot be null!"); - AuthorizeUrlBuilder.newInstance(DOMAIN, CLIENT_ID, REDIRECT_URI) - .withAudience(null); + verifyThrows(IllegalArgumentException.class, + () -> AuthorizeUrlBuilder.newInstance(DOMAIN, CLIENT_ID, REDIRECT_URI) + .withAudience(null), + "'audience' cannot be null!"); } @Test @@ -131,10 +126,10 @@ public void shouldSetState() { @Test public void shouldThrowWhenStateIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'state' cannot be null!"); - AuthorizeUrlBuilder.newInstance(DOMAIN, CLIENT_ID, REDIRECT_URI) - .withState(null); + verifyThrows(IllegalArgumentException.class, + () -> AuthorizeUrlBuilder.newInstance(DOMAIN, CLIENT_ID, REDIRECT_URI) + .withState(null), + "'state' cannot be null!"); } @Test @@ -147,10 +142,10 @@ public void shouldSetScope() { @Test public void shouldThrowWhenScopeIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'scope' cannot be null!"); - AuthorizeUrlBuilder.newInstance(DOMAIN, CLIENT_ID, REDIRECT_URI) - .withScope(null); + verifyThrows(IllegalArgumentException.class, + () -> AuthorizeUrlBuilder.newInstance(DOMAIN, CLIENT_ID, REDIRECT_URI) + .withScope(null), + "'scope' cannot be null!"); } @Test @@ -163,10 +158,10 @@ public void shouldSetResponseType() { @Test public void shouldThrowWhenResponseTypeIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'response type' cannot be null!"); - AuthorizeUrlBuilder.newInstance(DOMAIN, CLIENT_ID, REDIRECT_URI) - .withResponseType(null); + verifyThrows(IllegalArgumentException.class, + () -> AuthorizeUrlBuilder.newInstance(DOMAIN, CLIENT_ID, REDIRECT_URI) + .withResponseType(null), + "'response type' cannot be null!"); } @Test @@ -179,18 +174,18 @@ public void shouldSetCustomParameter() { @Test public void shouldThrowWhenCustomParameterNameIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'name' cannot be null!"); - AuthorizeUrlBuilder.newInstance(DOMAIN, CLIENT_ID, REDIRECT_URI) - .withParameter(null, "value"); + verifyThrows(IllegalArgumentException.class, + () -> AuthorizeUrlBuilder.newInstance(DOMAIN, CLIENT_ID, REDIRECT_URI) + .withParameter(null, "value"), + "'name' cannot be null!"); } @Test public void shouldThrowWhenCustomParameterValueIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'value' cannot be null!"); - AuthorizeUrlBuilder.newInstance(DOMAIN, CLIENT_ID, REDIRECT_URI) - .withParameter("name", null); + verifyThrows(IllegalArgumentException.class, + () -> AuthorizeUrlBuilder.newInstance(DOMAIN, CLIENT_ID, REDIRECT_URI) + .withParameter("name", null), + "'value' cannot be null!"); } @Test @@ -203,11 +198,11 @@ public void shouldAddOrganizationParameter() { @Test public void shouldThrowWhenOrganizationIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'organization' cannot be null!"); - AuthorizeUrlBuilder.newInstance(DOMAIN, CLIENT_ID, REDIRECT_URI) - .withOrganization(null) - .build(); + verifyThrows(IllegalArgumentException.class, + () -> AuthorizeUrlBuilder.newInstance(DOMAIN, CLIENT_ID, REDIRECT_URI) + .withOrganization(null) + .build(), + "'organization' cannot be null!"); } @Test @@ -220,10 +215,28 @@ public void shouldAddInvitationParameter() { @Test public void shouldThrowWhenInvitationIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'invitation' cannot be null!"); - AuthorizeUrlBuilder.newInstance(DOMAIN, CLIENT_ID, REDIRECT_URI) - .withInvitation(null) + verifyThrows(IllegalArgumentException.class, + () -> AuthorizeUrlBuilder.newInstance(DOMAIN, CLIENT_ID, REDIRECT_URI) + .withInvitation(null) + .build(), + "'invitation' cannot be null!"); + } + + @Test + public void shouldAddCodeChallengeParameter() { + String authUrl = AuthorizeUrlBuilder.newInstance(DOMAIN, CLIENT_ID, REDIRECT_URI) + .withCodeChallenge("insecure_challenge") .build(); + assertThat(authUrl, hasQueryParameter("code_challenge", "insecure_challenge")); + assertThat(authUrl, hasQueryParameter("code_challenge_method", "S256")); + } + + @Test + public void shouldThrowWhenChallengeIsNull() { + verifyThrows(IllegalArgumentException.class, + () -> AuthorizeUrlBuilder.newInstance(DOMAIN, CLIENT_ID, REDIRECT_URI) + .withCodeChallenge(null) + .build(), + "'challenge' cannot be null!"); } } diff --git a/src/test/java/com/auth0/client/auth/LogoutUrlBuilderTest.java b/src/test/java/com/auth0/client/auth/LogoutUrlBuilderTest.java index 59390a1a4..792d69eb9 100644 --- a/src/test/java/com/auth0/client/auth/LogoutUrlBuilderTest.java +++ b/src/test/java/com/auth0/client/auth/LogoutUrlBuilderTest.java @@ -1,12 +1,11 @@ package com.auth0.client.auth; import okhttp3.HttpUrl; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; +import org.junit.jupiter.api.Test; import java.net.URLEncoder; +import static com.auth0.AssertsUtil.verifyThrows; import static com.auth0.client.UrlMatcher.*; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; @@ -18,22 +17,18 @@ public class LogoutUrlBuilderTest { private static final String CLIENT_ID = "clientId"; private static final String RETURN_TO_URL = "https://domain.auth0.com/callback"; - @SuppressWarnings("deprecation") - @Rule - public ExpectedException exception = ExpectedException.none(); - @Test public void shouldThrowWhenBaseUrlIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'base url' cannot be null!"); - LogoutUrlBuilder.newInstance(null, CLIENT_ID, RETURN_TO_URL, true); + verifyThrows(IllegalArgumentException.class, + () -> LogoutUrlBuilder.newInstance(null, CLIENT_ID, RETURN_TO_URL, true), + "'base url' cannot be null!"); } @Test public void shouldThrowWhenReturnToURLIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'return to url' cannot be null!"); - LogoutUrlBuilder.newInstance(DOMAIN, CLIENT_ID, null, true); + verifyThrows(IllegalArgumentException.class, + () -> LogoutUrlBuilder.newInstance(DOMAIN, CLIENT_ID, null, true), + "'return to url' cannot be null!"); } @Test diff --git a/src/test/java/com/auth0/client/auth/RSAClientAssertionSignerTest.java b/src/test/java/com/auth0/client/auth/RSAClientAssertionSignerTest.java new file mode 100644 index 000000000..dfadc9e65 --- /dev/null +++ b/src/test/java/com/auth0/client/auth/RSAClientAssertionSignerTest.java @@ -0,0 +1,151 @@ +package com.auth0.client.auth; + +import com.auth0.AssertsUtil; +import com.auth0.exception.ClientAssertionSigningException; +import com.auth0.jwt.JWT; +import com.auth0.jwt.JWTCreator; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.exceptions.JWTCreationException; +import com.auth0.jwt.interfaces.DecodedJWT; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.net.URI; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.EncodedKeySpec; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; +import java.util.Base64; + +import static com.auth0.AssertsUtil.verifyThrows; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class RSAClientAssertionSignerTest { + + private static final String PRIVATE_KEY_FILE_RSA = "src/test/resources/auth/rsa_private_key.pem"; + private static final String PUBLIC_KEY_FILE_RSA = "src/test/resources/auth/rsa_public_key.pem"; + + @Test + public void defaultsToRS256() { + RSAPrivateKey privateKey = mock(RSAPrivateKey.class); + RSAClientAssertionSigner rsa = new RSAClientAssertionSigner(privateKey); + assertThat(rsa.getAssertionSigningAlgorithm(), is(RSAClientAssertionSigner.RSASigningAlgorithm.RSA256)); + } + + @Test + public void throwsOnNullSigningKey() { + AssertsUtil.verifyThrows(IllegalArgumentException.class, + () -> new RSAClientAssertionSigner(null), + "'assertion signing key' cannot be null!"); + } + + @Test + public void throwsOnNullSigningAlgorithm() { + RSAPrivateKey privateKey = mock(RSAPrivateKey.class); + verifyThrows(IllegalArgumentException.class, + () -> new RSAClientAssertionSigner(privateKey, null), + "'assertion signing algorithm' cannot be null!"); + } + + @Test + public void throwsWhenErrorSigning256() { + JWTCreator.Builder mockBuilder = mock(JWTCreator.Builder.class); + RSAPrivateKey mockPrivateKey = mock(RSAPrivateKey.class); + + when(mockBuilder.sign(Algorithm.RSA256(null,mockPrivateKey))).thenThrow(JWTCreationException.class); + + ClientAssertionSigningException e = verifyThrows(ClientAssertionSigningException.class, + () -> new RSAClientAssertionSigner(mockPrivateKey).createSignedClientAssertion("iss", "aud", "sub"), + "Error creating the JWT used for client assertion using the RSA256 signing algorithm"); + + assertThat(e.getCause(), is(instanceOf(JWTCreationException.class))); + } + + @Test + public void throwsWhenErrorSigning384() { + JWTCreator.Builder mockBuilder = mock(JWTCreator.Builder.class); + RSAPrivateKey mockPrivateKey = mock(RSAPrivateKey.class); + + when(mockBuilder.sign(Algorithm.RSA384(null,mockPrivateKey))).thenThrow(JWTCreationException.class); + + ClientAssertionSigningException e = verifyThrows(ClientAssertionSigningException.class, + () -> new RSAClientAssertionSigner(mockPrivateKey, RSAClientAssertionSigner.RSASigningAlgorithm.RSA384).createSignedClientAssertion("iss", "aud", "sub"), + "Error creating the JWT used for client assertion using the RSA384 signing algorithm"); + + assertThat(e.getCause(), is(instanceOf(JWTCreationException.class))); + } + + @Test + public void createsVerifiedRSA256SigningAssertion() throws Exception { + KeyPair keyPair = getKeyPair(); + + RSAClientAssertionSigner clientAssertion = new RSAClientAssertionSigner((RSAPrivateKey) keyPair.getPrivate()); + String jwt = clientAssertion.createSignedClientAssertion("issuer", "audience", "subject"); + + DecodedJWT decodedJWT = JWT.require(Algorithm.RSA256((RSAPublicKey) keyPair.getPublic(), null)) + .build() + .verify(jwt); + + assertThat(decodedJWT.getSubject(), is("subject")); + assertThat(decodedJWT.getAudience(), hasItem("audience")); + assertThat(decodedJWT.getIssuer(), is("issuer")); + assertThat(decodedJWT.getExpiresAtAsInstant(), is(decodedJWT.getIssuedAtAsInstant().plusSeconds(180))); + assertThat(decodedJWT.getClaim("jti").asString(), is(notNullValue())); + + + System.out.println(decodedJWT); + } + + @Test + public void createsVerifiedRSA384SigningAssertion() throws Exception { + KeyPair keyPair = getKeyPair(); + + RSAClientAssertionSigner clientAssertion = new RSAClientAssertionSigner((RSAPrivateKey) keyPair.getPrivate(), RSAClientAssertionSigner.RSASigningAlgorithm.RSA384); + String jwt = clientAssertion.createSignedClientAssertion("issuer", "audience", "subject"); + + DecodedJWT decodedJWT = JWT.require(Algorithm.RSA384((RSAPublicKey) keyPair.getPublic(), null)) + .build() + .verify(jwt); + + assertThat(decodedJWT.getSubject(), is("subject")); + assertThat(decodedJWT.getAudience(), hasItem("audience")); + assertThat(decodedJWT.getIssuer(), is("issuer")); + assertThat(decodedJWT.getExpiresAtAsInstant(), is(decodedJWT.getIssuedAtAsInstant().plusSeconds(180))); + assertThat(decodedJWT.getClaim("jti").asString(), is(notNullValue())); + + + System.out.println(decodedJWT); + } + + private KeyPair getKeyPair() throws Exception { + URI fileUri = new File(PRIVATE_KEY_FILE_RSA).toURI(); + String privateKeyContent = new String(Files.readAllBytes(Paths.get(fileUri))); + privateKeyContent = privateKeyContent.replaceAll("\\n", "").replace("-----BEGIN PRIVATE KEY-----", "").replace("-----END PRIVATE KEY-----", ""); + + KeyFactory kf = KeyFactory.getInstance("RSA"); + + PKCS8EncodedKeySpec keySpecPKCS8 = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKeyContent)); + PrivateKey privateKey = kf.generatePrivate(keySpecPKCS8); + + URI publicKeyFileUri = new File(PUBLIC_KEY_FILE_RSA).toURI(); + String publicKeyContent = new String(Files.readAllBytes(Paths.get(publicKeyFileUri))); + publicKeyContent = publicKeyContent.replaceAll("\\n", "").replace("-----BEGIN PUBLIC KEY-----", "").replace("-----END PUBLIC KEY-----", ""); + + byte[] encodedPublicKey = Base64.getDecoder().decode(publicKeyContent); + + EncodedKeySpec keySpec = new X509EncodedKeySpec(encodedPublicKey); + PublicKey publicKey = kf.generatePublic(keySpec); + + return new KeyPair(publicKey, privateKey); + } +} diff --git a/src/test/java/com/auth0/client/mgmt/ActionsEntityTest.java b/src/test/java/com/auth0/client/mgmt/ActionsEntityTest.java index 4da5c38ad..9554fdcae 100644 --- a/src/test/java/com/auth0/client/mgmt/ActionsEntityTest.java +++ b/src/test/java/com/auth0/client/mgmt/ActionsEntityTest.java @@ -5,11 +5,14 @@ import com.auth0.client.mgmt.filter.PageFilter; import com.auth0.json.mgmt.actions.*; import com.auth0.net.Request; +import com.auth0.net.Response; +import com.auth0.net.client.HttpMethod; import okhttp3.mockwebserver.RecordedRequest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.*; +import static com.auth0.AssertsUtil.verifyThrows; import static com.auth0.client.MockServer.bodyFromRequest; import static com.auth0.client.MockServer.readFromRequest; import static com.auth0.client.RecordedRequestMatcher.*; @@ -21,9 +24,9 @@ public class ActionsEntityTest extends BaseMgmtEntityTest { @Test public void getActionShouldThrowOnNullActionId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("action ID"); - api.actions().get(null); + verifyThrows(IllegalArgumentException.class, + () -> api.actions().get(null), + "'action ID' cannot be null!"); } @Test @@ -32,10 +35,10 @@ public void shouldGetAction() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MockServer.ACTION, 200); - Action response = request.execute(); + Action response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/actions/actions/action-id")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/actions/actions/action-id")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -44,9 +47,9 @@ public void shouldGetAction() throws Exception { @Test public void createActionShouldThrowOnNullAction() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("action"); - api.actions().create(null); + verifyThrows(IllegalArgumentException.class, + () -> api.actions().create(null), + "'action' cannot be null!"); } @Test @@ -71,10 +74,10 @@ public void shouldCreateAction() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MockServer.ACTION, 200); - Action response = request.execute(); + Response response = request.execute(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/api/v2/actions/actions")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/actions/actions")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -107,13 +110,15 @@ public void shouldCreateAction() throws Exception { assertThat(secretsOnRequest.get(0), hasEntry("value", secret.getValue())); assertThat(response, is(notNullValue())); + assertThat(response.getBody(), is(instanceOf(Action.class))); + assertThat(response.getStatusCode(), is(200)); } @Test public void deleteActionShouldThrowWhenActionIdIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("action ID"); - api.actions().delete(null); + verifyThrows(IllegalArgumentException.class, + () -> api.actions().delete(null), + "'action ID' cannot be null!"); } @Test @@ -122,10 +127,10 @@ public void shouldDeleteAction() throws Exception { assertThat(request, is(notNullValue())); server.emptyResponse(204); - request.execute(); + request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("DELETE", "/api/v2/actions/actions/action-id")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/actions/actions/action-id")); assertThat(recordedRequest, hasQueryParameter("force", "false")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -137,10 +142,10 @@ public void shouldForceDeleteAction() throws Exception { assertThat(request, is(notNullValue())); server.emptyResponse(204); - request.execute(); + request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("DELETE", "/api/v2/actions/actions/action-id")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/actions/actions/action-id")); assertThat(recordedRequest, hasQueryParameter("force", "true")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -152,10 +157,10 @@ public void shouldGetActionTriggers() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MockServer.ACTION_TRIGGERS, 200); - Triggers triggers = request.execute(); + Triggers triggers = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/actions/triggers")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/actions/triggers")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -165,16 +170,16 @@ public void shouldGetActionTriggers() throws Exception { @Test public void updateActionShouldThrowWhenActionIdIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("action ID"); - api.actions().update(null, new Action()); + verifyThrows(IllegalArgumentException.class, + () -> api.actions().update(null, new Action()), + "'action ID' cannot be null!"); } @Test public void updateActionShouldThrowWhenActionIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("action"); - api.actions().update("action-id", null); + verifyThrows(IllegalArgumentException.class, + () -> api.actions().update("action-id", null), + "'action' cannot be null!"); } @Test @@ -193,10 +198,10 @@ public void shouldUpdateAction() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MockServer.ACTION, 200); - Action response = request.execute(); + Action response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("PATCH", "/api/v2/actions/actions/action-id")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PATCH, "/api/v2/actions/actions/action-id")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -225,9 +230,9 @@ public void shouldUpdateAction() throws Exception { @Test public void deployActionShouldThrowWhenActionIdIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("action ID"); - api.actions().deploy(null); + verifyThrows(IllegalArgumentException.class, + () -> api.actions().deploy(null), + "'action ID' cannot be null!"); } @Test @@ -236,10 +241,10 @@ public void shouldDeployAction() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MockServer.ACTION_VERSION, 200); - Version response = request.execute(); + Version response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/api/v2/actions/actions/action-id/deploy")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/actions/actions/action-id/deploy")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest.getBody(), is(notNullValue())); @@ -250,16 +255,16 @@ public void shouldDeployAction() throws Exception { @Test public void getVersionShouldThrowWhenActionIdIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("action ID"); - api.actions().getVersion(null, "version-id"); + verifyThrows(IllegalArgumentException.class, + () -> api.actions().getVersion(null, "version-id"), + "'action ID' cannot be null!"); } @Test public void getVersionShouldThrowWhenVersionIdIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("action version ID"); - api.actions().getVersion("action-id", null); + verifyThrows(IllegalArgumentException.class, + () -> api.actions().getVersion("action-id", null), + "'action version ID' cannot be null!"); } @Test @@ -268,10 +273,10 @@ public void shouldGetActionVersion() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MockServer.ACTION_VERSION, 200); - Version response = request.execute(); + Version response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/actions/actions/action-id/versions/version-id")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/actions/actions/action-id/versions/version-id")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -280,16 +285,16 @@ public void shouldGetActionVersion() throws Exception { @Test public void rollBackToVersionShouldThrowWhenActionIdIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("action ID"); - api.actions().rollBackToVersion(null, "version-id"); + verifyThrows(IllegalArgumentException.class, + () -> api.actions().rollBackToVersion(null, "version-id"), + "'action ID' cannot be null!"); } @Test public void rollbackToVersionShouldThrowWhenVersionIdIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("action version ID"); - api.actions().rollBackToVersion("action-id", null); + verifyThrows(IllegalArgumentException.class, + () -> api.actions().rollBackToVersion("action-id", null), + "'action version ID' cannot be null!"); } @Test @@ -298,10 +303,10 @@ public void shouldRollBackActionVersion() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MockServer.ACTION_VERSION, 200); - Version response = request.execute(); + Version response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/api/v2/actions/actions/action-id/versions/version-id/deploy")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/actions/actions/action-id/versions/version-id/deploy")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest.getBody(), is(notNullValue())); @@ -312,9 +317,9 @@ public void shouldRollBackActionVersion() throws Exception { @Test public void getExecutionShouldThrowWhenExecutionIdIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("execution ID"); - api.actions().getExecution( null); + verifyThrows(IllegalArgumentException.class, + () -> api.actions().getExecution(null), + "'execution ID' cannot be null!"); } @Test @@ -323,10 +328,10 @@ public void shouldGetExecution() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MockServer.ACTION_EXECUTION, 200); - Execution response = request.execute(); + Execution response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/actions/executions/execution-id")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/actions/executions/execution-id")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -339,10 +344,10 @@ public void shouldListActionsWithNoFilter() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MockServer.ACTIONS_LIST, 200); - ActionsPage response = request.execute(); + ActionsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/actions/actions")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/actions/actions")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -362,10 +367,10 @@ public void shouldListActionsWithFilter() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MockServer.ACTIONS_LIST, 200); - ActionsPage response = request.execute(); + ActionsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/actions/actions")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/actions/actions")); assertThat(recordedRequest, hasQueryParameter("actionName", "action-name")); assertThat(recordedRequest, hasQueryParameter("deployed", "true")); assertThat(recordedRequest, hasQueryParameter("installed", "false")); @@ -380,9 +385,9 @@ public void shouldListActionsWithFilter() throws Exception { @Test public void getActionVetsionsShouldThrowWhenActionIdIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("action ID"); - api.actions().getVersions(null, null); + verifyThrows(IllegalArgumentException.class, + () -> api.actions().getVersions(null, null), + "'action ID' cannot be null!"); } @Test @@ -391,10 +396,10 @@ public void shouldGetActionVersionsWithNoFilter() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MockServer.ACTION_VERSIONS_LIST, 200); - VersionsPage response = request.execute(); + VersionsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/actions/actions/action-id/versions")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/actions/actions/action-id/versions")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -410,10 +415,10 @@ public void shouldGetActionVersionsWithFilter() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MockServer.ACTION_VERSIONS_LIST, 200); - VersionsPage response = request.execute(); + VersionsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/actions/actions/action-id/versions")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/actions/actions/action-id/versions")); assertThat(recordedRequest, hasQueryParameter("page", "1")); assertThat(recordedRequest, hasQueryParameter("per_page", "10")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); @@ -424,9 +429,9 @@ public void shouldGetActionVersionsWithFilter() throws Exception { @Test public void getTriggerBindingsShouldThrowWhenTriggerIdIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("trigger ID"); - api.actions().getTriggerBindings(null, null); + verifyThrows(IllegalArgumentException.class, + () -> api.actions().getTriggerBindings(null, null), + "'trigger ID' cannot be null!"); } @Test @@ -435,10 +440,10 @@ public void shouldGetTriggerBindingsWithNoFilter() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MockServer.ACTION_TRIGGER_BINDINGS, 200); - BindingsPage response = request.execute(); + BindingsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/actions/triggers/trigger-id/bindings")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/actions/triggers/trigger-id/bindings")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -454,10 +459,10 @@ public void shouldGetTriggerBindingsWithFilter() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MockServer.ACTION_TRIGGER_BINDINGS, 200); - BindingsPage response = request.execute(); + BindingsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/actions/triggers/trigger-id/bindings")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/actions/triggers/trigger-id/bindings")); assertThat(recordedRequest, hasQueryParameter("page", "1")); assertThat(recordedRequest, hasQueryParameter("per_page", "10")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); @@ -468,16 +473,16 @@ public void shouldGetTriggerBindingsWithFilter() throws Exception { @Test public void updateTriggerBindingsShouldThrowWhenTriggerIdIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("trigger ID"); - api.actions().updateTriggerBindings(null, null); + verifyThrows(IllegalArgumentException.class, + () -> api.actions().updateTriggerBindings(null, null), + "'trigger ID' cannot be null!"); } @Test public void updateTriggerBindingsShouldThrowWhenRequestBodyIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("request body"); - api.actions().updateTriggerBindings("triggeId", null); + verifyThrows(IllegalArgumentException.class, + () -> api.actions().updateTriggerBindings("triggerId", null), + "'request body' cannot be null!"); } @Test @@ -495,10 +500,10 @@ public void shouldUpdateTriggerBinding() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MockServer.ACTION_TRIGGER_BINDINGS, 200); - BindingsPage response = request.execute(); + BindingsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("PATCH", "/api/v2/actions/triggers/trigger-id/bindings")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PATCH, "/api/v2/actions/triggers/trigger-id/bindings")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); diff --git a/src/test/java/com/auth0/client/mgmt/AttackProtectionEntityTest.java b/src/test/java/com/auth0/client/mgmt/AttackProtectionEntityTest.java index 54398a2be..089f5c9a4 100644 --- a/src/test/java/com/auth0/client/mgmt/AttackProtectionEntityTest.java +++ b/src/test/java/com/auth0/client/mgmt/AttackProtectionEntityTest.java @@ -2,13 +2,15 @@ import com.auth0.json.mgmt.attackprotection.*; import com.auth0.net.Request; +import com.auth0.net.client.HttpMethod; import okhttp3.mockwebserver.RecordedRequest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.Arrays; import java.util.List; import java.util.Map; +import static com.auth0.AssertsUtil.verifyThrows; import static com.auth0.client.MockServer.*; import static com.auth0.client.RecordedRequestMatcher.hasHeader; import static com.auth0.client.RecordedRequestMatcher.hasMethodAndPath; @@ -23,10 +25,10 @@ public void shouldListBreachedPasswordSettings() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(BREACHED_PASSWORD_SETTINGS, 200); - BreachedPassword response = request.execute(); + BreachedPassword response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/attack-protection/breached-password-detection")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/attack-protection/breached-password-detection")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -39,35 +41,43 @@ public void shouldListBreachedPasswordSettings() throws Exception { assertThat(response.getAdminNotificationFrequency(), is(notNullValue())); assertThat(response.getAdminNotificationFrequency().size(), is(2)); assertThat(response.getAdminNotificationFrequency(), contains("immediately", "weekly")); + assertThat(response.getStage().getPreUserRegistrationStage().getShields(), contains("admin_notification")); } @Test public void shouldUpdateBreachedPasswordSettings() throws Exception { + BreachedPasswordStage stage = new BreachedPasswordStage(); + BreachedPasswordStageEntry preReg = new BreachedPasswordStageEntry(); + preReg.setShields(Arrays.asList("admin_notification")); + stage.setPreUserRegistrationStage(preReg); + BreachedPassword breachedPassword = new BreachedPassword(); breachedPassword.setEnabled(true); breachedPassword.setMethod("standard"); breachedPassword.setAdminNotificationFrequency(Arrays.asList("immediately", "daily")); breachedPassword.setShields(Arrays.asList("admin_notification", "block")); + breachedPassword.setStage(stage); Request request = api.attackProtection().updateBreachedPasswordSettings(breachedPassword); assertThat(request, is(notNullValue())); server.jsonResponse(BREACHED_PASSWORD_SETTINGS, 200); - BreachedPassword response = request.execute(); + BreachedPassword response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("PATCH", "/api/v2/attack-protection/breached-password-detection")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PATCH, "/api/v2/attack-protection/breached-password-detection")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); Map body = bodyFromRequest(recordedRequest); System.out.println(body); - assertThat(body.size(), is(4)); + assertThat(body.size(), is(5)); assertThat(body.get("method"), is("standard")); assertThat(body.get("enabled"), is(true)); assertThat(((List)body.get("shields")).size(), is(2)); assertThat((List) body.get("shields"), contains("admin_notification", "block")); + assertThat(body.get("stage"), is(notNullValue())); assertThat(response, is(notNullValue())); } @@ -78,10 +88,10 @@ public void shouldGetBruteForceConfiguration() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(BRUTE_FORCE_CONFIGURATION, 200); - BruteForceConfiguration response = request.execute(); + BruteForceConfiguration response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/attack-protection/brute-force-protection")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/attack-protection/brute-force-protection")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -115,10 +125,10 @@ public void shouldUpdateBruteForceConfiguration() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(BRUTE_FORCE_CONFIGURATION, 200); - BruteForceConfiguration response = request.execute(); + BruteForceConfiguration response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("PATCH", "/api/v2/attack-protection/brute-force-protection")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PATCH, "/api/v2/attack-protection/brute-force-protection")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -140,10 +150,10 @@ public void shouldGetSuspiciousIPThrottlingConfig() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(SUSPICIOUS_IP_THROTTLING_CONFIGURATION, 200); - SuspiciousIPThrottlingConfiguration response = request.execute(); + SuspiciousIPThrottlingConfiguration response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/attack-protection/suspicious-ip-throttling")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/attack-protection/suspicious-ip-throttling")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -190,10 +200,10 @@ public void shouldUpdateSuspiciousIPTThrottlingConfig() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(BRUTE_FORCE_CONFIGURATION, 200); - SuspiciousIPThrottlingConfiguration response = request.execute(); + SuspiciousIPThrottlingConfiguration response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("PATCH", "/api/v2/attack-protection/suspicious-ip-throttling")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PATCH, "/api/v2/attack-protection/suspicious-ip-throttling")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -210,22 +220,22 @@ public void shouldUpdateSuspiciousIPTThrottlingConfig() throws Exception { @Test public void updateBreachedPasswordSettingsShouldThrowWithNullParam() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("breached password"); - api.attackProtection().updateBreachedPasswordSettings(null); + verifyThrows(IllegalArgumentException.class, + () -> api.attackProtection().updateBreachedPasswordSettings(null), + "'breached password' cannot be null!"); } @Test public void updateBruteForceConfigurationShouldThrowWithNullParam() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("configuration"); - api.attackProtection().updateBruteForceConfiguration(null); + verifyThrows(IllegalArgumentException.class, + () -> api.attackProtection().updateBruteForceConfiguration(null), + "'configuration' cannot be null!"); } @Test public void updateSuspiciousIPThrottlingConfigurationShouldThrowWithNullParam() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("configuration"); - api.attackProtection().updateSuspiciousIPThrottlingConfiguration(null); + verifyThrows(IllegalArgumentException.class, + () -> api.attackProtection().updateSuspiciousIPThrottlingConfiguration(null), + "'configuration' cannot be null!"); } } diff --git a/src/test/java/com/auth0/client/mgmt/BaseMgmtEntityTest.java b/src/test/java/com/auth0/client/mgmt/BaseMgmtEntityTest.java index b9d7926c7..26d4d32da 100644 --- a/src/test/java/com/auth0/client/mgmt/BaseMgmtEntityTest.java +++ b/src/test/java/com/auth0/client/mgmt/BaseMgmtEntityTest.java @@ -1,10 +1,8 @@ package com.auth0.client.mgmt; import com.auth0.client.MockServer; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.rules.ExpectedException; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; public class BaseMgmtEntityTest { @@ -13,17 +11,13 @@ public class BaseMgmtEntityTest { protected MockServer server; protected ManagementAPI api; - @SuppressWarnings("deprecation") - @Rule - public ExpectedException exception = ExpectedException.none(); - - @Before + @BeforeEach public void setUp() throws Exception { server = new MockServer(); - api = new ManagementAPI(server.getBaseUrl(), API_TOKEN); + api = ManagementAPI.newBuilder(server.getBaseUrl(), API_TOKEN).build(); } - @After + @AfterEach public void tearDown() throws Exception { server.stop(); } diff --git a/src/test/java/com/auth0/client/mgmt/BlacklistsEntityTest.java b/src/test/java/com/auth0/client/mgmt/BlacklistsEntityTest.java index 488639c9c..da351714e 100644 --- a/src/test/java/com/auth0/client/mgmt/BlacklistsEntityTest.java +++ b/src/test/java/com/auth0/client/mgmt/BlacklistsEntityTest.java @@ -1,25 +1,27 @@ package com.auth0.client.mgmt; -import com.auth0.json.mgmt.Token; +import com.auth0.json.mgmt.blacklists.Token; import com.auth0.net.Request; +import com.auth0.net.client.HttpMethod; import okhttp3.mockwebserver.RecordedRequest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.List; import java.util.Map; +import static com.auth0.AssertsUtil.verifyThrows; import static com.auth0.client.MockServer.*; import static com.auth0.client.RecordedRequestMatcher.*; -import static org.hamcrest.Matchers.*; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; public class BlacklistsEntityTest extends BaseMgmtEntityTest { @Test public void shouldThrowOnGetBlacklistedTokensWithNullAudience() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'audience' cannot be null!"); - api.blacklists().getBlacklist(null); + verifyThrows(IllegalArgumentException.class, + () -> api.blacklists().getBlacklist(null), + "'audience' cannot be null!"); } @Test @@ -28,10 +30,10 @@ public void shouldGetBlacklistedTokens() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_BLACKLISTED_TOKENS_LIST, 200); - List response = request.execute(); + List response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/blacklists/tokens")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/blacklists/tokens")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("aud", "myapi")); @@ -46,7 +48,7 @@ public void shouldReturnEmptyBlacklistedTokens() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_EMPTY_LIST, 200); - List response = request.execute(); + List response = request.execute().getBody(); assertThat(response, is(notNullValue())); assertThat(response, is(emptyCollectionOf(Token.class))); @@ -54,9 +56,9 @@ public void shouldReturnEmptyBlacklistedTokens() throws Exception { @Test public void shouldThrowOnBlacklistTokensWithNullToken() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'token' cannot be null!"); - api.blacklists().blacklistToken(null); + verifyThrows(IllegalArgumentException.class, + () -> api.blacklists().blacklistToken(null), + "'token' cannot be null!"); } @Test @@ -65,10 +67,10 @@ public void shouldBlacklistToken() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_BLACKLISTED_TOKENS_LIST, 200); - request.execute(); + request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/api/v2/blacklists/tokens")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/blacklists/tokens")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); diff --git a/src/test/java/com/auth0/client/mgmt/BrandingEntityTest.java b/src/test/java/com/auth0/client/mgmt/BrandingEntityTest.java index 3788e9447..0889073a3 100644 --- a/src/test/java/com/auth0/client/mgmt/BrandingEntityTest.java +++ b/src/test/java/com/auth0/client/mgmt/BrandingEntityTest.java @@ -2,9 +2,11 @@ import com.auth0.json.mgmt.branding.*; import com.auth0.net.Request; +import com.auth0.net.client.HttpMethod; import okhttp3.mockwebserver.RecordedRequest; -import org.junit.Test; +import org.junit.jupiter.api.Test; +import static com.auth0.AssertsUtil.verifyThrows; import static com.auth0.client.MockServer.MGMT_BRANDING_LOGIN_TEMPLATE; import static com.auth0.client.MockServer.MGMT_BRANDING_SETTINGS; import static com.auth0.client.RecordedRequestMatcher.hasHeader; @@ -20,10 +22,10 @@ public void shouldGetBrandingSettings() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_BRANDING_SETTINGS, 200); - BrandingSettings response = request.execute(); + BrandingSettings response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/branding")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/branding")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -32,9 +34,9 @@ public void shouldGetBrandingSettings() throws Exception { @Test public void shouldThrowOnUpdateBrandingSettingsWithNullSettings() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'settings' cannot be null!"); - api.branding().updateBrandingSettings(null); + verifyThrows(IllegalArgumentException.class, + () -> api.branding().updateBrandingSettings(null), + "'settings' cannot be null!"); } @Test @@ -43,10 +45,10 @@ public void shouldUpdateBrandingSettings() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_BRANDING_SETTINGS, 200); - BrandingSettings response = request.execute(); + BrandingSettings response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("PATCH", "/api/v2/branding")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PATCH, "/api/v2/branding")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -59,10 +61,10 @@ public void shouldGetTheUniversalLoginTemplate() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_BRANDING_LOGIN_TEMPLATE, 200); - UniversalLoginTemplate response = request.execute(); + UniversalLoginTemplate response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/branding/templates/universal-login")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/branding/templates/universal-login")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -75,19 +77,19 @@ public void shouldDeleteTheUniversalLoginTemplate() throws Exception { assertThat(request, is(notNullValue())); server.emptyResponse(200); - request.execute(); + request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("DELETE", "/api/v2/branding/templates/universal-login")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/branding/templates/universal-login")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); } @Test public void shouldThrowOnSetUniversalLoginTemplateNullTemplate() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'template' cannot be null!"); - api.branding().setUniversalLoginTemplate(null); + verifyThrows(IllegalArgumentException.class, + () -> api.branding().setUniversalLoginTemplate(null), + "'template' cannot be null!"); } @Test @@ -96,10 +98,10 @@ public void shouldSetTheUniversalLoginTemplate() throws Exception { assertThat(request, is(notNullValue())); server.emptyResponse(204); - request.execute(); + request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("PUT", "/api/v2/branding/templates/universal-login")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PUT, "/api/v2/branding/templates/universal-login")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); } diff --git a/src/test/java/com/auth0/client/mgmt/ClientGrantsEntityTest.java b/src/test/java/com/auth0/client/mgmt/ClientGrantsEntityTest.java index 346ab76d0..8d810c947 100644 --- a/src/test/java/com/auth0/client/mgmt/ClientGrantsEntityTest.java +++ b/src/test/java/com/auth0/client/mgmt/ClientGrantsEntityTest.java @@ -1,20 +1,23 @@ package com.auth0.client.mgmt; import com.auth0.client.mgmt.filter.ClientGrantsFilter; -import com.auth0.json.mgmt.ClientGrant; -import com.auth0.json.mgmt.ClientGrantsPage; +import com.auth0.client.mgmt.filter.PageFilter; +import com.auth0.json.mgmt.clientgrants.ClientGrant; +import com.auth0.json.mgmt.clientgrants.ClientGrantsPage; +import com.auth0.json.mgmt.organizations.OrganizationsPage; import com.auth0.net.Request; +import com.auth0.net.client.HttpMethod; import okhttp3.mockwebserver.RecordedRequest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.ArrayList; -import java.util.List; import java.util.Map; +import static com.auth0.AssertsUtil.verifyThrows; import static com.auth0.client.MockServer.*; import static com.auth0.client.RecordedRequestMatcher.*; -import static org.hamcrest.Matchers.*; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; public class ClientGrantsEntityTest extends BaseMgmtEntityTest { @@ -24,10 +27,10 @@ public void shouldListClientGrantsWithoutFilter() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_CLIENT_GRANTS_LIST, 200); - ClientGrantsPage response = request.execute(); + ClientGrantsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/client-grants")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/client-grants")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -42,10 +45,10 @@ public void shouldListClientGrantsWithPage() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_CLIENT_GRANTS_LIST, 200); - ClientGrantsPage response = request.execute(); + ClientGrantsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/client-grants")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/client-grants")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("page", "23")); @@ -62,10 +65,10 @@ public void shouldListClientGrantsWithTotals() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_CLIENT_GRANTS_PAGED_LIST, 200); - ClientGrantsPage response = request.execute(); + ClientGrantsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/client-grants")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/client-grants")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("include_totals", "true")); @@ -82,105 +85,127 @@ public void shouldListClientGrantsWithTotals() throws Exception { public void shouldListClientGrantsWithAdditionalProperties() throws Exception { ClientGrantsFilter filter = new ClientGrantsFilter() .withAudience("https://myapi.auth0.com") + .withAllowAnyOrganization(true) .withClientId("u9e3hh3e9j2fj9092ked"); Request request = api.clientGrants().list(filter); assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_CLIENT_GRANTS_LIST, 200); - ClientGrantsPage response = request.execute(); + ClientGrantsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/client-grants")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/client-grants")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("audience", "https://myapi.auth0.com")); assertThat(recordedRequest, hasQueryParameter("client_id", "u9e3hh3e9j2fj9092ked")); + assertThat(recordedRequest, hasQueryParameter("allow_any_organization", "true")); assertThat(response, is(notNullValue())); assertThat(response.getItems(), hasSize(2)); } + @Test + public void shouldThrowOnCreateClientGrantWithNullClientId() { + verifyThrows(IllegalArgumentException.class, + () -> api.clientGrants().create(null, "audience", new String[]{"openid"}), + "'client id' cannot be null!"); + } + + @Test + public void shouldThrowOnCreateClientGrantWithNullAudience() { + verifyThrows(IllegalArgumentException.class, + () -> api.clientGrants().create("clientId", null, new String[]{"openid"}), + "'audience' cannot be null!"); + } + + @Test + public void shouldThrowOnCreateClientGrantWithNullScope() { + verifyThrows(IllegalArgumentException.class, + () -> api.clientGrants().create("clientId", "audience", null), + "'scope' cannot be null!"); + } @Test - public void shouldListClientGrants() throws Exception { - @SuppressWarnings("deprecation") - Request> request = api.clientGrants().list(); + public void shouldCreateClientGrant() throws Exception { + Request request = api.clientGrants().create("clientId", "audience", new String[]{"openid"}); assertThat(request, is(notNullValue())); - server.jsonResponse(MGMT_CLIENT_GRANTS_LIST, 200); - List response = request.execute(); + server.jsonResponse(MGMT_CLIENT_GRANT, 200); + ClientGrant response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/client-grants")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/client-grants")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + Map body = bodyFromRequest(recordedRequest); + assertThat(body.size(), is(3)); + assertThat(body, hasEntry("client_id", "clientId")); + assertThat(body, hasEntry("audience", "audience")); + assertThat(body, hasKey("scope")); + assertThat((Iterable) body.get("scope"), contains("openid")); + assertThat(body, not(hasKey("organization_usage"))); + assertThat(body, not(hasKey("allow_any_organization"))); + assertThat(response, is(notNullValue())); - assertThat(response, hasSize(2)); } @Test - public void shouldReturnEmptyClientGrants() throws Exception { - @SuppressWarnings("deprecation") - Request> request = api.clientGrants().list(); + public void shouldCreateClientGrantWithOrgParams() throws Exception { + Request request = api.clientGrants().create("clientId", "audience", new String[]{"openid"}, "allow", false); assertThat(request, is(notNullValue())); - server.jsonResponse(MGMT_EMPTY_LIST, 200); - List response = request.execute(); - - assertThat(response, is(notNullValue())); - assertThat(response, is(emptyCollectionOf(ClientGrant.class))); - } + server.jsonResponse(MGMT_CLIENT_GRANT, 200); + ClientGrant response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); - @Test - public void shouldThrowOnCreateClientGrantWithNullClientId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'client id' cannot be null!"); - api.clientGrants().create(null, "audience", new String[]{"openid"}); - } + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/client-grants")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); - @Test - public void shouldThrowOnCreateClientGrantWithNullAudience() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'audience' cannot be null!"); - api.clientGrants().create("clientId", null, new String[]{"openid"}); - } + Map body = bodyFromRequest(recordedRequest); + assertThat(body.size(), is(5)); + assertThat(body, hasEntry("client_id", "clientId")); + assertThat(body, hasEntry("audience", "audience")); + assertThat(body, hasKey("scope")); + assertThat((Iterable) body.get("scope"), contains("openid")); + assertThat(body, hasEntry("organization_usage", "allow")); + assertThat(body, hasEntry("allow_any_organization", false)); - @Test - public void shouldThrowOnCreateClientGrantWithNullScope() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'scope' cannot be null!"); - api.clientGrants().create("clientId", "audience", null); + assertThat(response, is(notNullValue())); } @Test - public void shouldCreateClientGrant() throws Exception { - Request request = api.clientGrants().create("clientId", "audience", new String[]{"openid"}); + public void createClientGrantWithOrgParamsShouldNotSendEmptyOrgUsage() throws Exception { + Request request = api.clientGrants().create("clientId", "audience", new String[]{"openid"}, " ", false); assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_CLIENT_GRANT, 200); - ClientGrant response = request.execute(); + ClientGrant response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/api/v2/client-grants")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/client-grants")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); Map body = bodyFromRequest(recordedRequest); - assertThat(body.size(), is(3)); + assertThat(body.size(), is(4)); assertThat(body, hasEntry("client_id", "clientId")); assertThat(body, hasEntry("audience", "audience")); assertThat(body, hasKey("scope")); assertThat((Iterable) body.get("scope"), contains("openid")); + assertThat(body, not(hasKey("organization_usage"))); + assertThat(body, hasEntry("allow_any_organization", false)); assertThat(response, is(notNullValue())); } @Test public void shouldThrowOnDeleteClientGrantWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'client grant id' cannot be null!"); - api.clientGrants().delete(null); + verifyThrows(IllegalArgumentException.class, + () -> api.clientGrants().delete(null), + "'client grant id' cannot be null!"); } @Test @@ -189,26 +214,26 @@ public void shouldDeleteClientGrant() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_CLIENT_GRANT, 200); - request.execute(); + request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("DELETE", "/api/v2/client-grants/1")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/client-grants/1")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); } @Test public void shouldThrowOnUpdateClientGrantWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'client grant id' cannot be null!"); - api.clientGrants().update(null, new String[]{}); + verifyThrows(IllegalArgumentException.class, + () -> api.clientGrants().update(null, new String[]{}), + "'client grant id' cannot be null!"); } @Test public void shouldThrowOnUpdateClientGrantWithNullScope() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'scope' cannot be null!"); - api.clientGrants().update("clientGrantId", null); + verifyThrows(IllegalArgumentException.class, + () -> api.clientGrants().update("clientGrantId", null), + "'scope' cannot be null!"); } @Test @@ -217,18 +242,107 @@ public void shouldUpdateClientGrant() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_CLIENT_GRANT, 200); - ClientGrant response = request.execute(); + ClientGrant response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("PATCH", "/api/v2/client-grants/1")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PATCH, "/api/v2/client-grants/1")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); Map body = bodyFromRequest(recordedRequest); assertThat(body.size(), is(1)); assertThat((ArrayList) body.get("scope"), contains("openid", "profile")); + assertThat(body, not(hasKey("organization_usage"))); + assertThat(body, not(hasKey("allow_any_organization"))); assertThat(response, is(notNullValue())); } + @Test + public void shouldUpdateClientGrantWithOrgParams() throws Exception { + Request request = api.clientGrants().update("1", new String[]{"openid", "profile"}, "allow", true); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_CLIENT_GRANT, 200); + ClientGrant response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PATCH, "/api/v2/client-grants/1")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + Map body = bodyFromRequest(recordedRequest); + assertThat(body.size(), is(3)); + assertThat((ArrayList) body.get("scope"), contains("openid", "profile")); + assertThat(body, hasEntry("organization_usage", "allow")); + assertThat(body, hasEntry("allow_any_organization", true)); + + assertThat(response, is(notNullValue())); + } + + @Test + public void updateClientGrantWithOrgParamsShouldNotSendEmptyOrgUsage() throws Exception { + Request request = api.clientGrants().update("1", new String[]{"openid", "profile"}, " ", true); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_CLIENT_GRANT, 200); + ClientGrant response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PATCH, "/api/v2/client-grants/1")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + Map body = bodyFromRequest(recordedRequest); + assertThat(body.size(), is(2)); + assertThat((ArrayList) body.get("scope"), contains("openid", "profile")); + assertThat(body, not(hasKey("organization_usage"))); + assertThat(body, hasEntry("allow_any_organization", true)); + + assertThat(response, is(notNullValue())); + } + + @Test + public void shouldListOrganizationsWithoutFilter() throws Exception { + Request request = api.clientGrants().listOrganizations("grant-id", null); + assertThat(request, is(notNullValue())); + + server.jsonResponse(ORGANIZATIONS_LIST, 200); + OrganizationsPage response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/client-grants/grant-id/organizations")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + assertThat(response, is(notNullValue())); + assertThat(response.getItems(), hasSize(2)); + } + + @Test + public void shouldListOrganizationsWithPage() throws Exception { + PageFilter filter = new PageFilter().withPage(23, 5); + Request request = api.clientGrants().listOrganizations("grant-id", filter); + assertThat(request, is(notNullValue())); + + server.jsonResponse(ORGANIZATIONS_PAGED_LIST, 200); + OrganizationsPage response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/client-grants/grant-id/organizations")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + assertThat(recordedRequest, hasQueryParameter("page", "23")); + assertThat(recordedRequest, hasQueryParameter("per_page", "5")); + + assertThat(response, is(notNullValue())); + assertThat(response.getItems(), hasSize(2)); + } + + @Test + public void shouldThrowOnGetOrganizationsWithNullId() { + verifyThrows(IllegalArgumentException.class, + () -> api.clientGrants().listOrganizations(null, new PageFilter()), + "'client grant ID' cannot be null!"); + } } diff --git a/src/test/java/com/auth0/client/mgmt/ClientsEntityTest.java b/src/test/java/com/auth0/client/mgmt/ClientsEntityTest.java index 40ea540d1..d46008662 100644 --- a/src/test/java/com/auth0/client/mgmt/ClientsEntityTest.java +++ b/src/test/java/com/auth0/client/mgmt/ClientsEntityTest.java @@ -4,17 +4,22 @@ import com.auth0.client.mgmt.filter.FieldsFilter; import com.auth0.json.mgmt.client.Client; import com.auth0.json.mgmt.client.ClientsPage; +import com.auth0.json.mgmt.client.Credential; +import com.auth0.json.mgmt.tokenquota.ClientCredentials; +import com.auth0.json.mgmt.tokenquota.TokenQuota; import com.auth0.net.Request; +import com.auth0.net.client.HttpMethod; import okhttp3.mockwebserver.RecordedRequest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.List; import java.util.Map; +import static com.auth0.AssertsUtil.verifyThrows; import static com.auth0.client.MockServer.*; import static com.auth0.client.RecordedRequestMatcher.*; -import static org.hamcrest.Matchers.*; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; public class ClientsEntityTest extends BaseMgmtEntityTest { @@ -24,10 +29,10 @@ public void shouldListClientsWithoutFilter() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_CLIENTS_LIST, 200); - ClientsPage response = request.execute(); + ClientsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/clients")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/clients")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -42,10 +47,10 @@ public void shouldListClientsWithPage() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_CLIENTS_LIST, 200); - ClientsPage response = request.execute(); + ClientsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/clients")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/clients")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("page", "23")); @@ -62,10 +67,10 @@ public void shouldListClientsWithTotals() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_CLIENTS_PAGED_LIST, 200); - ClientsPage response = request.execute(); + ClientsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/clients")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/clients")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("include_totals", "true")); @@ -85,10 +90,10 @@ public void shouldListClientsWithFields() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_CLIENTS_PAGED_LIST, 200); - ClientsPage response = request.execute(); + ClientsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/clients")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/clients")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("fields", "some,random,fields")); @@ -108,10 +113,10 @@ public void shouldListClientsWithAdditionalProperties() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_CLIENTS_LIST, 200); - ClientsPage response = request.execute(); + ClientsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/clients")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/clients")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("app_type", "regular_web,native")); @@ -123,41 +128,29 @@ public void shouldListClientsWithAdditionalProperties() throws Exception { } @Test - public void shouldListClients() throws Exception { - @SuppressWarnings("deprecation") - Request> request = api.clients().list(); + public void shouldListClientsWithQuery() throws Exception { + ClientFilter filter = new ClientFilter().withQuery("client_grant.organization_id:" + "org_123"); + Request request = api.clients().list(filter); assertThat(request, is(notNullValue())); - server.jsonResponse(MGMT_CLIENTS_LIST, 200); - List response = request.execute(); + server.jsonResponse(MGMT_CLIENTS_PAGED_LIST, 200); + ClientsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/clients")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/clients")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + assertThat(recordedRequest, hasQueryParameter("q", "client_grant.organization_id:" + "org_123")); assertThat(response, is(notNullValue())); - assertThat(response, hasSize(2)); - } - - @Test - public void shouldReturnEmptyClients() throws Exception { - @SuppressWarnings("deprecation") - Request> request = api.clients().list(); - assertThat(request, is(notNullValue())); - - server.jsonResponse(MGMT_EMPTY_LIST, 200); - List response = request.execute(); - - assertThat(response, is(notNullValue())); - assertThat(response, is(emptyCollectionOf(Client.class))); + assertThat(response.getItems(), hasSize(2)); } @Test public void shouldThrowOnGetClientWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'client id' cannot be null!"); - api.clients().get(null); + verifyThrows(IllegalArgumentException.class, + () -> api.clients().get(null), + "'client id' cannot be null!"); } @Test @@ -166,13 +159,12 @@ public void shouldGetClient() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_CLIENT, 200); - Client response = request.execute(); + Client response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/clients/1")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/clients/1")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); - assertThat(response, is(notNullValue())); } @@ -185,10 +177,10 @@ public void shouldGetClientWithFilter() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_CLIENT, 200); - Client response = request.execute(); + Client response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/clients/1")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/clients/1")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("fields", "name,client_id,app_type,tenant")); @@ -203,10 +195,10 @@ public void shouldGetClientWithNullFilter() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_CLIENT, 200); - Client response = request.execute(); + Client response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/clients/1")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/clients/1")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -215,36 +207,53 @@ public void shouldGetClientWithNullFilter() throws Exception { @Test public void shouldThrowOnCreateClientWithNullData() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'client' cannot be null!"); - api.clients().create(null); + verifyThrows(IllegalArgumentException.class, + () -> api.clients().create(null), + "'client' cannot be null!"); } @Test public void shouldCreateClient() throws Exception { - Request request = api.clients().create(new Client("My Application")); + Client clientCreate = new Client("My Application"); + ClientCredentials clientCredentials = new ClientCredentials(); + clientCredentials.setPerDay(100); + clientCredentials.setPerHour(20); + clientCredentials.setEnforce(true); + + TokenQuota tokenQuota = new TokenQuota(clientCredentials); + clientCreate.setTokenQuota(tokenQuota); + Request request = api.clients().create(clientCreate); assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_CLIENT, 200); - Client response = request.execute(); + Client response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/api/v2/clients")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/clients")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); Map body = bodyFromRequest(recordedRequest); - assertThat(body.size(), is(1)); + assertThat(body.size(), is(2)); assertThat(body, hasEntry("name", "My Application")); + // Verify the token_quota structure + Map tokenQuotaMap = (Map) body.get("token_quota"); + assertThat(tokenQuotaMap, is(notNullValue())); + Map clientCredentialsMap = (Map) tokenQuotaMap.get("client_credentials"); + assertThat(clientCredentialsMap, is(notNullValue())); + assertThat(clientCredentialsMap, hasEntry("per_day", 100)); + assertThat(clientCredentialsMap, hasEntry("per_hour", 20)); + assertThat(clientCredentialsMap, hasEntry("enforce", true)); + assertThat(response, is(notNullValue())); } @Test public void shouldThrowOnDeleteClientWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'client id' cannot be null!"); - api.clients().delete(null); + verifyThrows(IllegalArgumentException.class, + () -> api.clients().delete(null), + "'client id' cannot be null!"); } @Test @@ -253,53 +262,70 @@ public void shouldDeleteClient() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_CLIENT, 200); - request.execute(); + request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("DELETE", "/api/v2/clients/1")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/clients/1")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); } @Test public void shouldThrowOnUpdateClientWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'client id' cannot be null!"); - api.clients().update(null, new Client("name")); + verifyThrows(IllegalArgumentException.class, + () -> api.clients().update(null, new Client("name")), + "'client id' cannot be null!"); } @Test public void shouldThrowOnUpdateClientWithNullData() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'client' cannot be null!"); - api.clients().update("clientId", null); + verifyThrows(IllegalArgumentException.class, + () -> api.clients().update("clientId", null), + "'client' cannot be null!"); } @Test public void shouldUpdateClient() throws Exception { - Request request = api.clients().update("1", new Client("My Application")); + Client clientUpdate = new Client( "My Application"); + ClientCredentials clientCredentials = new ClientCredentials(); + clientCredentials.setPerDay(100); + clientCredentials.setPerHour(20); + clientCredentials.setEnforce(true); + + TokenQuota tokenQuota = new TokenQuota(clientCredentials); + clientUpdate.setTokenQuota(tokenQuota); + Request request = api.clients().update("1", clientUpdate); assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_CLIENT, 200); - Client response = request.execute(); + Client response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("PATCH", "/api/v2/clients/1")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PATCH, "/api/v2/clients/1")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); Map body = bodyFromRequest(recordedRequest); - assertThat(body.size(), is(1)); + assertThat(body.size(), is(2)); assertThat(body, hasEntry("name", "My Application")); + Map tokenQuotaMap = (Map) body.get("token_quota"); + assertThat(tokenQuotaMap, is(notNullValue())); + Map clientCredentialsMap = (Map) tokenQuotaMap.get("client_credentials"); + assertThat(clientCredentialsMap, is(notNullValue())); + assertThat(clientCredentialsMap, hasEntry("per_day", 100)); + assertThat(clientCredentialsMap, hasEntry("per_hour", 20)); + assertThat(clientCredentialsMap, hasEntry("enforce", true)); + + assertThat(response, is(notNullValue())); } @Test public void shouldThrowOnRotateClientSecretWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'client id' cannot be null!"); - api.clients().rotateSecret(null); + verifyThrows(IllegalArgumentException.class, + () -> api.clients().rotateSecret(null), + "'client id' cannot be null!"); } @Test @@ -308,10 +334,10 @@ public void shouldRotateClientSecret() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_CLIENT, 200); - Client response = request.execute(); + Client response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/api/v2/clients/1/rotate-secret")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/clients/1/rotate-secret")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Content-Length", "0")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -319,4 +345,163 @@ public void shouldRotateClientSecret() throws Exception { assertThat(response, is(notNullValue())); } + @Test + public void shouldListClientCredentials() throws Exception { + Request> request = api.clients().listCredentials("clientId"); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_CLIENT_CREDENTIAL_LIST, 200); + List response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/clients/clientId/credentials")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + assertThat(response, is(notNullValue())); + } + + @Test + public void shouldThrowOnListCredentialsWithNullClientId() { + verifyThrows(IllegalArgumentException.class, + () -> api.clients().listCredentials(null), + "'client id' cannot be null!"); + } + + @Test + public void shouldGetClientCredential() throws Exception { + Request request = api.clients().getCredential("clientId", "credId"); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_CLIENT_CREDENTIAL, 200); + Credential response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/clients/clientId/credentials/credId")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + assertThat(response, is(notNullValue())); + } + + @Test + public void shouldThrowOnGetCredentialsWithNullClientId() { + verifyThrows(IllegalArgumentException.class, + () -> api.clients().getCredential(null, "credId"), + "'client id' cannot be null!"); + } + + @Test + public void shouldThrowOnGetCredentialsWithNullCredentialId() { + verifyThrows(IllegalArgumentException.class, + () -> api.clients().getCredential("clientId", null), + "'credential id' cannot be null!"); + } + + @Test + public void shouldCreateClientCredential() throws Exception { + Credential credential = new Credential("public_key", "pem"); + Request request = api.clients().createCredential("clientId", credential); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_CLIENT_CREDENTIAL, 201); + Credential response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/clients/clientId/credentials")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + Map body = bodyFromRequest(recordedRequest); + assertThat(body.size(), is(2)); + assertThat(body, hasEntry("credential_type", "public_key")); + assertThat(body, hasEntry("pem", "pem")); + + assertThat(response, is(notNullValue())); + } + + @Test + public void shouldThrowOnCreateCredentialsWithNullClientId() { + verifyThrows(IllegalArgumentException.class, + () -> api.clients().createCredential(null, new Credential()), + "'client id' cannot be null!"); + } + + @Test + public void shouldThrowOnCreateCredentialsWithNullCredentialId() { + verifyThrows(IllegalArgumentException.class, + () -> api.clients().deleteCredential("clientId", null), + "'credential id' cannot be null!"); + } + + @Test + public void shouldDeleteCredential() throws Exception { + Request request = api.clients().deleteCredential("clientId", "credId"); + assertThat(request, is(notNullValue())); + + server.emptyResponse(204); + request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/clients/clientId/credentials/credId")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + } + + @Test + public void shouldThrowOnDeleteCredentialsWithNullClientId() { + verifyThrows(IllegalArgumentException.class, + () -> api.clients().deleteCredential(null, "credId"), + "'client id' cannot be null!"); + } + + @Test + public void shouldThrowOnDeleteCredentialsWithNullCredentialId() { + verifyThrows(IllegalArgumentException.class, + () -> api.clients().deleteCredential("clientId", null), + "'credential id' cannot be null!"); + } + + @Test + public void shouldUpdateClientCredential() throws Exception { + Credential credential = new Credential(); + credential.setName("Updated credential name"); + Request request = api.clients().updateCredential("clientId", "credId", credential); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_CLIENT_CREDENTIAL, 200); + Credential response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PATCH, "/api/v2/clients/clientId/credentials/credId")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + Map body = bodyFromRequest(recordedRequest); + assertThat(body.size(), is(1)); + assertThat(body, hasEntry("name", "Updated credential name")); + + assertThat(response, is(notNullValue())); + } + + @Test + public void shouldThrowOnUpdateCredentialWithNullClientId() { + verifyThrows(IllegalArgumentException.class, + () -> api.clients().updateCredential(null, "credId", new Credential()), + "'client id' cannot be null!"); + } + + @Test + public void shouldThrowOnUpdateCredentialWithNullCredentialId() { + verifyThrows(IllegalArgumentException.class, + () -> api.clients().updateCredential("clientId", null, new Credential()), + "'credential id' cannot be null!"); + } + + @Test + public void shouldThrowOnUpdateCredentialWithNullCredential() { + verifyThrows(IllegalArgumentException.class, + () -> api.clients().updateCredential("clientId", "credId", null), + "'credential' cannot be null!"); + } } diff --git a/src/test/java/com/auth0/client/mgmt/ConnectionsEntityTest.java b/src/test/java/com/auth0/client/mgmt/ConnectionsEntityTest.java index 351013fa0..bf19b4908 100644 --- a/src/test/java/com/auth0/client/mgmt/ConnectionsEntityTest.java +++ b/src/test/java/com/auth0/client/mgmt/ConnectionsEntityTest.java @@ -1,351 +1,717 @@ package com.auth0.client.mgmt; import com.auth0.client.mgmt.filter.ConnectionFilter; -import com.auth0.json.mgmt.Connection; -import com.auth0.json.mgmt.ConnectionsPage; +import com.auth0.client.mgmt.filter.EnabledClientsFilter; +import com.auth0.json.mgmt.connections.*; import com.auth0.net.Request; +import com.auth0.net.client.HttpMethod; import okhttp3.mockwebserver.RecordedRequest; -import org.junit.Test; +import org.junit.jupiter.api.Test; +import java.util.ArrayList; import java.util.List; import java.util.Map; +import static com.auth0.AssertsUtil.verifyThrows; import static com.auth0.client.MockServer.*; import static com.auth0.client.RecordedRequestMatcher.*; -import static org.hamcrest.Matchers.*; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; public class ConnectionsEntityTest extends BaseMgmtEntityTest { @Test - public void shouldListConnections() throws Exception { - @SuppressWarnings("deprecation") - Request> request = api.connections().list(null); + public void shouldListConnectionsWithoutFilter() throws Exception { + Request request = api.connections().listAll(null); assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_CONNECTIONS_LIST, 200); - List response = request.execute(); + ConnectionsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/connections")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/connections")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(response, is(notNullValue())); - assertThat(response, hasSize(2)); + assertThat(response.getItems(), hasSize(2)); } @Test - public void shouldListConnectionsWithStrategy() throws Exception { - ConnectionFilter filter = new ConnectionFilter().withStrategy("auth0"); - - @SuppressWarnings("deprecation") - Request> request = api.connections().list(filter); + public void shouldListConnectionsWithPage() throws Exception { + ConnectionFilter filter = new ConnectionFilter().withPage(23, 5); + Request request = api.connections().listAll(filter); assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_CONNECTIONS_LIST, 200); - List response = request.execute(); + ConnectionsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/connections")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/connections")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); - assertThat(recordedRequest, hasQueryParameter("strategy", "auth0")); + assertThat(recordedRequest, hasQueryParameter("page", "23")); + assertThat(recordedRequest, hasQueryParameter("per_page", "5")); assertThat(response, is(notNullValue())); - assertThat(response, hasSize(2)); + assertThat(response.getItems(), hasSize(2)); } @Test - public void shouldListConnectionsWithName() throws Exception { - ConnectionFilter filter = new ConnectionFilter().withName("my-connection"); - - @SuppressWarnings("deprecation") - Request> request = api.connections().list(filter); + public void shouldListConnectionsWithTotals() throws Exception { + ConnectionFilter filter = new ConnectionFilter().withTotals(true); + Request request = api.connections().listAll(filter); assertThat(request, is(notNullValue())); - server.jsonResponse(MGMT_CONNECTIONS_LIST, 200); - List response = request.execute(); + server.jsonResponse(MGMT_CONNECTIONS_PAGED_LIST, 200); + ConnectionsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/connections")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/connections")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); - assertThat(recordedRequest, hasQueryParameter("name", "my-connection")); + assertThat(recordedRequest, hasQueryParameter("include_totals", "true")); assertThat(response, is(notNullValue())); - assertThat(response, hasSize(2)); + assertThat(response.getItems(), hasSize(2)); + assertThat(response.getStart(), is(0)); + assertThat(response.getLength(), is(14)); + assertThat(response.getTotal(), is(14)); + assertThat(response.getLimit(), is(50)); } @Test - public void shouldListConnectionsWithFields() throws Exception { - ConnectionFilter filter = new ConnectionFilter().withFields("some,random,fields", true); - - @SuppressWarnings("deprecation") - Request> request = api.connections().list(filter); + public void shouldListConnectionsWithFrom() throws Exception { + ConnectionFilter filter = new ConnectionFilter().withFrom("10"); + Request request = api.connections().listAll(filter); assertThat(request, is(notNullValue())); - server.jsonResponse(MGMT_CONNECTIONS_LIST, 200); - List response = request.execute(); + server.jsonResponse(MGMT_CONNECTIONS_PAGED_LIST, 200); + ConnectionsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/connections")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/connections")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); - assertThat(recordedRequest, hasQueryParameter("fields", "some,random,fields")); - assertThat(recordedRequest, hasQueryParameter("include_fields", "true")); + assertThat(recordedRequest, hasQueryParameter("from", "10")); assertThat(response, is(notNullValue())); - assertThat(response, hasSize(2)); + assertThat(response.getItems(), hasSize(2)); + assertThat(response.getStart(), is(0)); + assertThat(response.getLength(), is(14)); + assertThat(response.getTotal(), is(14)); + assertThat(response.getLimit(), is(50)); } @Test - public void shouldListConnectionsWithoutFilter() throws Exception { - Request request = api.connections().listAll(null); + public void shouldListConnectionsWithTake() throws Exception { + ConnectionFilter filter = new ConnectionFilter().withTake(1); + Request request = api.connections().listAll(filter); assertThat(request, is(notNullValue())); - server.jsonResponse(MGMT_CONNECTIONS_LIST, 200); - ConnectionsPage response = request.execute(); + server.jsonResponse(MGMT_CONNECTIONS_PAGED_LIST, 200); + ConnectionsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/connections")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/connections")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + assertThat(recordedRequest, hasQueryParameter("take", "1")); assertThat(response, is(notNullValue())); assertThat(response.getItems(), hasSize(2)); + assertThat(response.getStart(), is(0)); + assertThat(response.getLength(), is(14)); + assertThat(response.getTotal(), is(14)); + assertThat(response.getLimit(), is(50)); } @Test - public void shouldNotListConnectionsWithTotals() throws Exception { - ConnectionFilter filter = new ConnectionFilter().withTotals(true); + public void shouldThrowOnGetConnectionWithNullId() { + verifyThrows(IllegalArgumentException.class, + () -> api.connections().get(null, null), + "'connection id' cannot be null!"); + } - @SuppressWarnings("deprecation") - Request> request = api.connections().list(filter); + @Test + public void shouldGetConnection() throws Exception { + Request request = api.connections().get("1", null); assertThat(request, is(notNullValue())); - server.jsonResponse(MGMT_CONNECTIONS_LIST, 200); - List response = request.execute(); + server.jsonResponse(MGMT_CONNECTION, 200); + Connection response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/connections")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/connections/1")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); - assertThat(recordedRequest, not(hasQueryParameter("include_totals"))); assertThat(response, is(notNullValue())); - assertThat(response, hasSize(2)); } @Test - public void shouldListConnectionsWithPage() throws Exception { - ConnectionFilter filter = new ConnectionFilter().withPage(23, 5); - Request request = api.connections().listAll(filter); + public void shouldGetConnectionWithFields() throws Exception { + ConnectionFilter filter = new ConnectionFilter().withFields("some,random,fields", true); + Request request = api.connections().get("1", filter); assertThat(request, is(notNullValue())); - server.jsonResponse(MGMT_CONNECTIONS_LIST, 200); - ConnectionsPage response = request.execute(); + server.jsonResponse(MGMT_CONNECTION, 200); + Connection response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/connections")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/connections/1")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); - assertThat(recordedRequest, hasQueryParameter("page", "23")); - assertThat(recordedRequest, hasQueryParameter("per_page", "5")); + assertThat(recordedRequest, hasQueryParameter("fields", "some,random,fields")); + assertThat(recordedRequest, hasQueryParameter("include_fields", "true")); assertThat(response, is(notNullValue())); - assertThat(response.getItems(), hasSize(2)); } @Test - public void shouldListConnectionsWithTotals() throws Exception { - ConnectionFilter filter = new ConnectionFilter().withTotals(true); - Request request = api.connections().listAll(filter); + public void shouldThrowOnCreateConnectionWithNullData() { + verifyThrows(IllegalArgumentException.class, + () -> api.connections().create(null), + "'connection' cannot be null!"); + } + + @Test + public void shouldCreateConnection() throws Exception { + Connection createConnection = new Connection("my-connection", "auth0"); + createConnection.setDomainConnection(true); + createConnection.setShowAsButton(true); + Request request = api.connections().create(createConnection); assertThat(request, is(notNullValue())); - server.jsonResponse(MGMT_CONNECTIONS_PAGED_LIST, 200); - ConnectionsPage response = request.execute(); + server.jsonResponse(MGMT_CONNECTION, 200); + Connection response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/connections")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/connections")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); - assertThat(recordedRequest, hasQueryParameter("include_totals", "true")); + + Map body = bodyFromRequest(recordedRequest); + assertThat(body.size(), is(4)); + assertThat(body, hasEntry("name", "my-connection")); + assertThat(body, hasEntry("strategy", "auth0")); assertThat(response, is(notNullValue())); - assertThat(response.getItems(), hasSize(2)); - assertThat(response.getStart(), is(0)); - assertThat(response.getLength(), is(14)); - assertThat(response.getTotal(), is(14)); - assertThat(response.getLimit(), is(50)); } + @Test + public void shouldThrowOnDeleteConnectionWithNullId() { + verifyThrows(IllegalArgumentException.class, + () -> api.connections().delete(null), + "'connection id' cannot be null!"); + } @Test - public void shouldReturnEmptyConnections() throws Exception { - @SuppressWarnings("deprecation") - Request> request = api.connections().list(null); + public void shouldDeleteConnection() throws Exception { + Request request = api.connections().delete("1"); assertThat(request, is(notNullValue())); - server.jsonResponse(MGMT_EMPTY_LIST, 200); - List response = request.execute(); + server.jsonResponse(MGMT_CONNECTION, 200); + request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); - assertThat(response, is(notNullValue())); - assertThat(response, is(emptyCollectionOf(Connection.class))); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/connections/1")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); } @Test - public void shouldThrowOnGetConnectionWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'connection id' cannot be null!"); - api.connections().get(null, null); + public void shouldThrowOnUpdateConnectionWithNullId() { + verifyThrows(IllegalArgumentException.class, + () -> api.connections().update(null, new Connection("my-connection", "auth0")), + "'connection id' cannot be null!"); } @Test - public void shouldGetConnection() throws Exception { - Request request = api.connections().get("1", null); + public void shouldThrowOnUpdateConnectionWithNullData() { + verifyThrows(IllegalArgumentException.class, + () -> api.connections().update("1", null), + "'connection' cannot be null!"); + } + + @Test + public void shouldUpdateConnection() throws Exception { + Request request = api.connections().update("1", new Connection("my-connection", "auth0")); assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_CONNECTION, 200); - Connection response = request.execute(); + Connection response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/connections/1")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PATCH, "/api/v2/connections/1")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + Map body = bodyFromRequest(recordedRequest); + assertThat(body.size(), is(2)); + assertThat(body, hasEntry("name", "my-connection")); + assertThat(body, hasEntry("strategy", "auth0")); + assertThat(response, is(notNullValue())); } @Test - public void shouldGetConnectionWithFields() throws Exception { - ConnectionFilter filter = new ConnectionFilter().withFields("some,random,fields", true); - Request request = api.connections().get("1", filter); + public void shouldThrowOnDeleteConnectionUserWithNullId() { + verifyThrows(IllegalArgumentException.class, + () -> api.connections().deleteUser(null, "user@domain.com"), + "'connection id' cannot be null!"); + } + + @Test + public void shouldThrowOnDeleteConnectionUserWithNullEmail() { + verifyThrows(IllegalArgumentException.class, + () -> api.connections().deleteUser("1", null), + "'email' cannot be null!"); + } + + @Test + public void shouldDeleteConnectionUser() throws Exception { + Request request = api.connections().deleteUser("1", "user@domain.com"); assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_CONNECTION, 200); - Connection response = request.execute(); + request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/connections/1")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/connections/1/users")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + assertThat(recordedRequest, hasQueryParameter("email", "user@domain.com")); + } + + @Test + public void shouldThrowOnGetScimConfigurationWithNullId() { + verifyThrows(IllegalArgumentException.class, + () -> api.connections().getScimConfiguration(null), + "'connection id' cannot be null!"); + } + + @Test + public void shouldGetScimConfiguration() throws Exception { + Request request = api.connections().getScimConfiguration("1"); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_CONNECTION_SCIM_CONFIGURATION, 200); + ScimConfigurationResponse response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/connections/1/scim-configuration")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); - assertThat(recordedRequest, hasQueryParameter("fields", "some,random,fields")); - assertThat(recordedRequest, hasQueryParameter("include_fields", "true")); assertThat(response, is(notNullValue())); } @Test - public void shouldThrowOnCreateConnectionWithNullData() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'connection' cannot be null!"); - api.connections().create(null); + public void shouldThrowOnDeleteScimConfigurationWithNullId() { + verifyThrows(IllegalArgumentException.class, + () -> api.connections().deleteScimConfiguration(null), + "'connection id' cannot be null!"); } @Test - public void shouldCreateConnection() throws Exception { - Request request = api.connections().create(new Connection("my-connection", "auth0")); + public void shouldDeleteScimConfiguration() throws Exception { + Request request = api.connections().deleteScimConfiguration("1"); assertThat(request, is(notNullValue())); - server.jsonResponse(MGMT_CONNECTION, 200); - Connection response = request.execute(); + server.jsonResponse(MGMT_CONNECTION_SCIM_CONFIGURATION, 200); + request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/connections/1/scim-configuration")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + } + + @Test + public void shouldThrowOnUpdateScimConfigurationWithNullId() { + verifyThrows(IllegalArgumentException.class, + () -> api.connections().updateScimConfiguration(null, null), + "'connection id' cannot be null!"); + } + + @Test + public void shouldThrowOnUpdateScimConfigurationWithNullScimConfigurationRequest() { + verifyThrows(IllegalArgumentException.class, + () -> api.connections().updateScimConfiguration("1", null), + "'scim configuration request' cannot be null!"); + } + + @Test + public void shouldThrowOnUpdateScimConfigurationWithNullUserIdAttribute() { + ScimConfigurationRequest request = new ScimConfigurationRequest(); + request.setMapping(getMappings()); + + verifyThrows(IllegalArgumentException.class, + () -> api.connections().updateScimConfiguration("1", request), + "'user id attribute' cannot be null!"); + } + + @Test + public void shouldThrowOnUpdateScimConfigurationWithNullMapping() { + ScimConfigurationRequest request = new ScimConfigurationRequest(); + request.setUserIdAttribute("externalId"); + + verifyThrows(IllegalArgumentException.class, + () -> api.connections().updateScimConfiguration("1", request), + "'mapping' cannot be null!"); + } + + @Test + public void shouldUpdateScimConfiguration() throws Exception { + ScimConfigurationRequest scimConfigurationRequest = getScimConfiguration(); + Request request = api.connections().updateScimConfiguration("1", scimConfigurationRequest); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_CONNECTION_SCIM_CONFIGURATION, 200); + ScimConfigurationResponse response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/api/v2/connections")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PATCH, "/api/v2/connections/1/scim-configuration")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); Map body = bodyFromRequest(recordedRequest); assertThat(body.size(), is(2)); - assertThat(body, hasEntry("name", "my-connection")); - assertThat(body, hasEntry("strategy", "auth0")); + assertThat(body, hasEntry("user_id_attribute", "externalId")); + assertThat(body, hasKey("mapping")); assertThat(response, is(notNullValue())); } @Test - public void shouldThrowOnDeleteConnectionWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'connection id' cannot be null!"); - api.connections().delete(null); + public void shouldThrowOnCreateScimConfigurationWithNullId() { + verifyThrows(IllegalArgumentException.class, + () -> api.connections().createScimConfiguration(null, getScimConfiguration()), + "'connection id' cannot be null!"); } @Test - public void shouldDeleteConnection() throws Exception { - Request request = api.connections().delete("1"); + public void shouldCreateScimConfiguration() throws Exception { + ScimConfigurationRequest scimConfigurationRequest = getScimConfiguration(); + Request request = api.connections().createScimConfiguration("1", scimConfigurationRequest); assertThat(request, is(notNullValue())); - server.jsonResponse(MGMT_CONNECTION, 200); - request.execute(); + server.jsonResponse(MGMT_CONNECTION_SCIM_CONFIGURATION, 200); + ScimConfigurationResponse response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("DELETE", "/api/v2/connections/1")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/connections/1/scim-configuration")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + Map body = bodyFromRequest(recordedRequest); + assertThat(body.size(), is(2)); + assertThat(body, hasEntry("user_id_attribute", "externalId")); + assertThat(body, hasKey("mapping")); + + assertThat(response, is(notNullValue())); } @Test - public void shouldThrowOnUpdateConnectionWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'connection id' cannot be null!"); - api.connections().update(null, new Connection("my-connection", "auth0")); + public void shouldThrowOnGetDefaultScimConfigurationWithNullId() { + verifyThrows(IllegalArgumentException.class, + () -> api.connections().createScimConfiguration(null, getScimConfiguration()), + "'connection id' cannot be null!"); } @Test - public void shouldThrowOnUpdateConnectionWithNullData() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'connection' cannot be null!"); - api.connections().update("1", null); + public void shouldGetDefaultScimConfiguration() throws Exception { + Request request = api.connections().getDefaultScimConfiguration("1"); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_CONNECTION_DEFAULT_SCIM_CONFIGURATION, 200); + DefaultScimMappingResponse response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/connections/1/scim-configuration/default-mapping")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + assertThat(response, is(notNullValue())); } @Test - public void shouldUpdateConnection() throws Exception { - Request request = api.connections().update("1", new Connection("my-connection", "auth0")); + public void shouldThrowOnGetScimTokenWithNullId() { + verifyThrows(IllegalArgumentException.class, + () -> api.connections().getScimToken(null), + "'connection id' cannot be null!"); + } + + @Test + public void shouldGetScimToken() throws Exception { + Request> request = api.connections().getScimToken("1"); assertThat(request, is(notNullValue())); - server.jsonResponse(MGMT_CONNECTION, 200); - Connection response = request.execute(); + server.jsonResponse(MGMT_CONNECTION_SCIM_TOKENS, 200); + List response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/connections/1/scim-configuration/tokens")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + assertThat(response, is(notNullValue())); + assertThat(response.size(), is(2)); + } + + @Test + public void shouldThrowOnCreateScimTokenWithNullId() { + ScimTokenRequest request = getScimToken(); + + verifyThrows(IllegalArgumentException.class, + () -> api.connections().createScimToken(null, request), + "'connection id' cannot be null!"); + } + + @Test + public void shouldThrowOnCreateScimTokenWithNullScimTokenRequest() { + verifyThrows(IllegalArgumentException.class, + () -> api.connections().createScimToken("1", null), + "'scim token request' cannot be null!"); + } + + @Test + public void shouldCreateScimToken() throws Exception { + ScimTokenRequest scimTokenRequest = getScimToken(); + Request request = api.connections().createScimToken("1", scimTokenRequest); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_CONNECTION_SCIM_TOKEN, 200); + ScimTokenBaseResponse response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("PATCH", "/api/v2/connections/1")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/connections/1/scim-configuration/tokens")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); Map body = bodyFromRequest(recordedRequest); assertThat(body.size(), is(2)); - assertThat(body, hasEntry("name", "my-connection")); - assertThat(body, hasEntry("strategy", "auth0")); + assertThat(body, hasKey("scopes")); assertThat(response, is(notNullValue())); } @Test - public void shouldThrowOnDeleteConnectionUserWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'connection id' cannot be null!"); - api.connections().deleteUser(null, "user@domain.com"); + public void shouldThrowOnDeleteScimTokenWithNullId() { + verifyThrows(IllegalArgumentException.class, + () -> api.connections().deleteScimToken(null, "1"), + "'connection id' cannot be null!"); } @Test - public void shouldThrowOnDeleteConnectionUserWithNullEmail() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'email' cannot be null!"); - api.connections().deleteUser("1", null); + public void shouldThrowOnDeleteScimTokenWithNullTokenId() { + verifyThrows(IllegalArgumentException.class, + () -> api.connections().deleteScimToken("1", null), + "'token id' cannot be null!"); } @Test - public void shouldDeleteConnectionUser() throws Exception { - Request request = api.connections().deleteUser("1", "user@domain.com"); + public void shouldDeleteScimToken() throws Exception { + Request request = api.connections().deleteScimToken("1", "1"); assertThat(request, is(notNullValue())); - server.jsonResponse(MGMT_CONNECTION, 200); - request.execute(); + server.jsonResponse(MGMT_CONNECTION_SCIM_CONFIGURATION, 200); + request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("DELETE", "/api/v2/connections/1/users")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/connections/1/scim-configuration/tokens/1")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + } + + @Test + public void shouldThrowOnCheckConnectionStatusWithNullId() { + verifyThrows(IllegalArgumentException.class, + () -> api.connections().checkConnectionStatus(null), + "'connection id' cannot be null!"); + } + + @Test + public void shouldCheckConnectionStatus() throws Exception { + Request request = api.connections().checkConnectionStatus("1"); + assertThat(request, is(notNullValue())); + + server.emptyResponse(204); + request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/connections/1/status")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); - assertThat(recordedRequest, hasQueryParameter("email", "user@domain.com")); } + + @Test + public void shouldThrowOnGetEnabledClientsWithNullId() { + verifyThrows(IllegalArgumentException.class, + () -> api.connections().getEnabledClients(null, new EnabledClientsFilter()), + "'connection id' cannot be null!"); + } + + @Test + public void shouldGetEnabledClientsWithoutFilter() throws Exception { + Request request = api.connections().getEnabledClients("1", null); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_ENABLED_CLIENTS_FOR_CONNECTION, 200); + EnabledClientResponse response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/connections/1/clients")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + assertThat(response, is(notNullValue())); + assertThat(response.getClients(), hasSize(2)); + } + + @Test + public void shouldGetEnabledClientsWithFromFilter() throws Exception { + EnabledClientsFilter filter = new EnabledClientsFilter().withFrom("1"); + Request request = api.connections().getEnabledClients("1", filter); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_ENABLED_CLIENTS_FOR_CONNECTION, 200); + EnabledClientResponse response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/connections/1/clients")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + assertThat(recordedRequest, hasQueryParameter("from", "1")); + + assertThat(response, is(notNullValue())); + assertThat(response.getClients(), hasSize(2)); + } + + @Test + public void shouldGetEnabledClientsWithTakeFilter() throws Exception { + EnabledClientsFilter filter = new EnabledClientsFilter().withTake(2); + Request request = api.connections().getEnabledClients("1", filter); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_ENABLED_CLIENTS_FOR_CONNECTION, 200); + EnabledClientResponse response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/connections/1/clients")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + assertThat(recordedRequest, hasQueryParameter("take", "2")); + + assertThat(response, is(notNullValue())); + assertThat(response.getClients(), hasSize(2)); + } + + @Test + public void shouldThrowOnUpdateEnabledClientsWithNullId() { + EnabledClientRequest clientRequest = new EnabledClientRequest("clientId", true); + List enabledClientRequests = new ArrayList<>(); + enabledClientRequests.add(clientRequest); + verifyThrows(IllegalArgumentException.class, + () -> api.connections().updateEnabledClients(null, enabledClientRequests), + "'connection id' cannot be null!"); + } + + @Test + public void shouldThrowOnUpdateEnabledClientsWithNullRequest() { +; verifyThrows(IllegalArgumentException.class, + () -> api.connections().updateEnabledClients("1", null), + "'enabled client Request' cannot be null!"); + } + + + @Test + public void shouldUpdateEnabledClients() throws Exception { + EnabledClientRequest clientRequest = new EnabledClientRequest("clientId", true); + List enabledClientRequests = new ArrayList<>(); + enabledClientRequests.add(clientRequest); + Request request = api.connections().updateEnabledClients("1", enabledClientRequests); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_ENABLED_CLIENTS_FOR_CONNECTION, 200); + request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PATCH, "/api/v2/connections/1/clients")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + List body = bodyListFromRequest(recordedRequest); + assertThat(body, is(notNullValue())); + } + + @Test + public void shouldThrowOnGetKeysWithNullId() { + verifyThrows(IllegalArgumentException.class, + () -> api.connections().getKeys(null), + "'connection id' cannot be null!"); + } + + @Test + public void shouldGetKeys() throws Exception { + Request> request = api.connections().getKeys("1"); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_CONNECTION_KEY, 200); + List response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/connections/1/keys")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + assertThat(response, is(notNullValue())); + } + + @Test + public void shouldThrowOnRotateKeyWithNullId() { + verifyThrows(IllegalArgumentException.class, + () -> api.connections().rotateKey(null), + "'connection id' cannot be null!"); + } + + @Test + public void shouldRotateKey() throws Exception { + Request request = api.connections().rotateKey("1"); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_ROTATE_KEY, 200); + RotateKey response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/connections/1/keys/rotate")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + assertThat(response, is(notNullValue())); + } + + private ScimTokenRequest getScimToken() { + ScimTokenRequest request = new ScimTokenRequest(); + List scopes = new ArrayList<>(); + scopes.add("get:users"); + request.setScopes(scopes); + request.setTokenLifetime(1000); + return request; + } + + private ScimConfigurationRequest getScimConfiguration() { + ScimConfigurationRequest request = new ScimConfigurationRequest(); + request.setUserIdAttribute("externalId"); + request.setMapping(getMappings()); + return request; + } + + private List getMappings() { + List mappingList = new ArrayList<>(); + mappingList.add(new Mapping("user_id", "id")); + return mappingList; + } + } diff --git a/src/test/java/com/auth0/client/mgmt/DeviceCredentialsEntityTest.java b/src/test/java/com/auth0/client/mgmt/DeviceCredentialsEntityTest.java index 85fe1ceb2..8bcfbf76f 100644 --- a/src/test/java/com/auth0/client/mgmt/DeviceCredentialsEntityTest.java +++ b/src/test/java/com/auth0/client/mgmt/DeviceCredentialsEntityTest.java @@ -1,18 +1,20 @@ package com.auth0.client.mgmt; +import com.auth0.AssertsUtil; import com.auth0.client.mgmt.filter.DeviceCredentialsFilter; -import com.auth0.json.mgmt.DeviceCredentials; +import com.auth0.json.mgmt.devicecredentials.DeviceCredentials; import com.auth0.net.Request; +import com.auth0.net.client.HttpMethod; import okhttp3.mockwebserver.RecordedRequest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.List; import java.util.Map; import static com.auth0.client.MockServer.*; import static com.auth0.client.RecordedRequestMatcher.*; -import static org.hamcrest.Matchers.*; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; public class DeviceCredentialsEntityTest extends BaseMgmtEntityTest { @Test @@ -21,10 +23,10 @@ public void shouldListDeviceCredentials() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_DEVICE_CREDENTIALS_LIST, 200); - List response = request.execute(); + List response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/device-credentials")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/device-credentials")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -39,10 +41,10 @@ public void shouldListDeviceCredentialsWithClientId() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_DEVICE_CREDENTIALS_LIST, 200); - List response = request.execute(); + List response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/device-credentials")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/device-credentials")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("client_id", "client_23")); @@ -58,10 +60,10 @@ public void shouldListDeviceCredentialsWithUserId() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_DEVICE_CREDENTIALS_LIST, 200); - List response = request.execute(); + List response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/device-credentials")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/device-credentials")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("user_id", "user_23")); @@ -78,10 +80,10 @@ public void shouldListDeviceCredentialsWithType() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_DEVICE_CREDENTIALS_LIST, 200); - List response = request.execute(); + List response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/device-credentials")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/device-credentials")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("type", "public_key")); @@ -98,10 +100,10 @@ public void shouldListDeviceCredentialsWithFields() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_DEVICE_CREDENTIALS_LIST, 200); - List response = request.execute(); + List response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/device-credentials")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/device-credentials")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("fields", "some,random,fields")); @@ -117,7 +119,7 @@ public void shouldReturnEmptyDeviceCredentials() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_EMPTY_LIST, 200); - List response = request.execute(); + List response = request.execute().getBody(); assertThat(response, is(notNullValue())); assertThat(response, is(emptyCollectionOf(DeviceCredentials.class))); @@ -125,9 +127,9 @@ public void shouldReturnEmptyDeviceCredentials() throws Exception { @Test public void shouldThrowOnCreateDeviceCredentialsWithNullData() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'device credentials' cannot be null!"); - api.deviceCredentials().create(null); + AssertsUtil.verifyThrows(IllegalArgumentException.class, + () -> api.deviceCredentials().create(null), + "'device credentials' cannot be null!"); } @Test @@ -136,10 +138,10 @@ public void shouldCreateDeviceCredentials() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_DEVICE_CREDENTIALS, 200); - DeviceCredentials response = request.execute(); + DeviceCredentials response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/api/v2/device-credentials")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/device-credentials")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -156,9 +158,9 @@ public void shouldCreateDeviceCredentials() throws Exception { @Test public void shouldThrowOnDeleteDeviceCredentialsWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'device credentials id' cannot be null!"); - api.deviceCredentials().delete(null); + AssertsUtil.verifyThrows(IllegalArgumentException.class, + () -> api.deviceCredentials().delete(null), + "'device credentials id' cannot be null!"); } @Test @@ -167,10 +169,10 @@ public void shouldDeleteDeviceCredentials() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_DEVICE_CREDENTIALS, 200); - request.execute(); + request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("DELETE", "/api/v2/device-credentials/1")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/device-credentials/1")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); } diff --git a/src/test/java/com/auth0/client/mgmt/EmailProviderEntityTest.java b/src/test/java/com/auth0/client/mgmt/EmailProviderEntityTest.java index ba2ab065a..0ac03337c 100644 --- a/src/test/java/com/auth0/client/mgmt/EmailProviderEntityTest.java +++ b/src/test/java/com/auth0/client/mgmt/EmailProviderEntityTest.java @@ -3,16 +3,18 @@ import com.auth0.client.mgmt.filter.FieldsFilter; import com.auth0.json.mgmt.emailproviders.EmailProvider; import com.auth0.net.Request; +import com.auth0.net.client.HttpMethod; import okhttp3.mockwebserver.RecordedRequest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.Map; +import static com.auth0.AssertsUtil.verifyThrows; import static com.auth0.client.MockServer.MGMT_EMAIL_PROVIDER; import static com.auth0.client.MockServer.bodyFromRequest; import static com.auth0.client.RecordedRequestMatcher.*; -import static org.hamcrest.Matchers.*; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; public class EmailProviderEntityTest extends BaseMgmtEntityTest { @Test @@ -21,10 +23,10 @@ public void shouldGetEmailProvider() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_EMAIL_PROVIDER, 200); - EmailProvider response = request.execute(); + EmailProvider response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/emails/provider")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/emails/provider")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -38,10 +40,10 @@ public void shouldGetEmailProviderWithFields() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_EMAIL_PROVIDER, 200); - EmailProvider response = request.execute(); + EmailProvider response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/emails/provider")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/emails/provider")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("fields", "some,random,fields")); @@ -52,9 +54,9 @@ public void shouldGetEmailProviderWithFields() throws Exception { @Test public void shouldThrowOnSetupEmailProviderWithNullData() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'email provider' cannot be null!"); - api.emailProvider().setup(null); + verifyThrows(IllegalArgumentException.class, + () -> api.emailProvider().setup(null), + "'email provider' cannot be null!"); } @Test @@ -63,10 +65,10 @@ public void shouldSetupEmailProvider() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_EMAIL_PROVIDER, 200); - EmailProvider response = request.execute(); + EmailProvider response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/api/v2/emails/provider")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/emails/provider")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -83,19 +85,19 @@ public void shouldDeleteEmailProvider() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_EMAIL_PROVIDER, 200); - request.execute(); + request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("DELETE", "/api/v2/emails/provider")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/emails/provider")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); } @Test public void shouldThrowOnUpdateEmailProviderWithNullData() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'email provider' cannot be null!"); - api.emailProvider().update(null); + verifyThrows(IllegalArgumentException.class, + () -> api.emailProvider().update(null), + "'email provider' cannot be null!"); } @Test @@ -104,10 +106,10 @@ public void shouldUpdateEmailProvider() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_EMAIL_PROVIDER, 200); - EmailProvider response = request.execute(); + EmailProvider response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("PATCH", "/api/v2/emails/provider")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PATCH, "/api/v2/emails/provider")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); diff --git a/src/test/java/com/auth0/client/mgmt/EmailTemplatesEntityTest.java b/src/test/java/com/auth0/client/mgmt/EmailTemplatesEntityTest.java index 1115c8b55..bfdec1fe8 100644 --- a/src/test/java/com/auth0/client/mgmt/EmailTemplatesEntityTest.java +++ b/src/test/java/com/auth0/client/mgmt/EmailTemplatesEntityTest.java @@ -1,17 +1,19 @@ package com.auth0.client.mgmt; -import com.auth0.json.mgmt.EmailTemplate; +import com.auth0.json.mgmt.emailtemplates.EmailTemplate; import com.auth0.net.Request; +import com.auth0.net.client.HttpMethod; import okhttp3.mockwebserver.RecordedRequest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.Map; +import static com.auth0.AssertsUtil.verifyThrows; import static com.auth0.client.MockServer.*; import static com.auth0.client.RecordedRequestMatcher.hasHeader; import static com.auth0.client.RecordedRequestMatcher.hasMethodAndPath; -import static org.hamcrest.Matchers.*; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; @SuppressWarnings("RedundantThrows") public class EmailTemplatesEntityTest extends BaseMgmtEntityTest { @@ -21,10 +23,10 @@ public void shouldGetEmailTemplate() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_EMAIL_TEMPLATE, 200); - EmailTemplate response = request.execute(); + EmailTemplate response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/email-templates/welcome_email")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/email-templates/welcome_email")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -33,9 +35,9 @@ public void shouldGetEmailTemplate() throws Exception { @Test public void shouldThrowOnGetEmailTemplateWithNullName() throws Exception { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'template name' cannot be null!"); - api.emailTemplates().get(null); + verifyThrows(IllegalArgumentException.class, + () -> api.emailTemplates().get(null), + "'template name' cannot be null!"); } @Test @@ -52,10 +54,10 @@ public void shouldCreateEmailTemplate() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_EMAIL_PROVIDER, 200); - EmailTemplate response = request.execute(); + EmailTemplate response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/api/v2/email-templates")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/email-templates")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -75,9 +77,9 @@ public void shouldCreateEmailTemplate() throws Exception { @Test public void shouldThrowOnCreateEmailTemplateWithNullData() throws Exception { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'template' cannot be null!"); - api.emailTemplates().create(null); + verifyThrows(IllegalArgumentException.class, + () -> api.emailTemplates().create(null), + "'template' cannot be null!"); } @Test @@ -91,10 +93,10 @@ public void shouldPatchEmailTemplate() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_EMAIL_PROVIDER, 200); - EmailTemplate response = request.execute(); + EmailTemplate response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("PATCH", "/api/v2/email-templates/welcome_email")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PATCH, "/api/v2/email-templates/welcome_email")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -113,15 +115,15 @@ public void shouldPatchEmailTemplate() throws Exception { @Test public void shouldThrowOnPatchEmailTemplateWithNullData() throws Exception { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'template' cannot be null!"); - api.emailTemplates().update("welcome_email", null); + verifyThrows(IllegalArgumentException.class, + () -> api.emailTemplates().update("welcome_email", null), + "'template' cannot be null!"); } @Test public void shouldThrowOnPatchEmailTemplateWithNullName() throws Exception { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'template name' cannot be null!"); - api.emailTemplates().update(null, new EmailTemplate()); + verifyThrows(IllegalArgumentException.class, + () -> api.emailTemplates().update(null, new EmailTemplate()), + "'template name' cannot be null!"); } } diff --git a/src/test/java/com/auth0/client/mgmt/GrantsEntityTest.java b/src/test/java/com/auth0/client/mgmt/GrantsEntityTest.java index 5e8ba9031..46c42a556 100644 --- a/src/test/java/com/auth0/client/mgmt/GrantsEntityTest.java +++ b/src/test/java/com/auth0/client/mgmt/GrantsEntityTest.java @@ -1,18 +1,18 @@ package com.auth0.client.mgmt; import com.auth0.client.mgmt.filter.GrantsFilter; -import com.auth0.json.mgmt.Grant; -import com.auth0.json.mgmt.GrantsPage; +import com.auth0.json.mgmt.grants.GrantsPage; import com.auth0.net.Request; +import com.auth0.net.client.HttpMethod; import okhttp3.mockwebserver.RecordedRequest; -import org.junit.Test; +import org.junit.jupiter.api.Test; -import java.util.List; - -import static com.auth0.client.MockServer.*; +import static com.auth0.AssertsUtil.verifyThrows; +import static com.auth0.client.MockServer.MGMT_GRANTS_LIST; +import static com.auth0.client.MockServer.MGMT_GRANTS_PAGED_LIST; import static com.auth0.client.RecordedRequestMatcher.*; -import static org.hamcrest.Matchers.*; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; public class GrantsEntityTest extends BaseMgmtEntityTest { @@ -22,10 +22,10 @@ public void shouldListGrantsWithoutFilter() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_GRANTS_LIST, 200); - GrantsPage response = request.execute(); + GrantsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/grants")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/grants")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("user_id", "userId")); @@ -36,9 +36,9 @@ public void shouldListGrantsWithoutFilter() throws Exception { @Test public void shouldThrowOnListGrantsWithoutFilterWithNullUserId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'user id' cannot be null!"); - api.grants().list(null, null); + verifyThrows(IllegalArgumentException.class, + () -> api.grants().list(null, null), + "'user id' cannot be null!"); } @Test @@ -48,10 +48,10 @@ public void shouldListGrantsWithPage() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_GRANTS_LIST, 200); - GrantsPage response = request.execute(); + GrantsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/grants")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/grants")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("user_id", "userId")); @@ -69,10 +69,10 @@ public void shouldListGrantsWithTotals() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_GRANTS_PAGED_LIST, 200); - GrantsPage response = request.execute(); + GrantsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/grants")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/grants")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("user_id", "userId")); @@ -95,10 +95,10 @@ public void shouldListGrantsWithAdditionalProperties() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_GRANTS_LIST, 200); - GrantsPage response = request.execute(); + GrantsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/grants")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/grants")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("user_id", "userId")); @@ -109,60 +109,11 @@ public void shouldListGrantsWithAdditionalProperties() throws Exception { assertThat(response.getItems(), hasSize(2)); } - - @Test - public void shouldListGrants() throws Exception { - @SuppressWarnings("deprecation") - Request> request = api.grants().list("userId"); - assertThat(request, is(notNullValue())); - - server.jsonResponse(MGMT_GRANTS_LIST, 200); - List response = request.execute(); - RecordedRequest recordedRequest = server.takeRequest(); - - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/grants")); - assertThat(recordedRequest, hasQueryParameter("user_id", "userId")); - assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); - assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); - - assertThat(response, is(notNullValue())); - assertThat(response, hasSize(2)); - for (Grant grant : response) { - assertThat(grant.getAudience(), notNullValue()); - assertThat(grant.getClientId(), notNullValue()); - assertThat(grant.getId(), notNullValue()); - assertThat(grant.getScope(), notNullValue()); - assertThat(grant.getScope(), hasSize(2)); - assertThat(grant.getUserId(), equalTo("userId")); - } - } - - @SuppressWarnings("deprecation") - @Test - public void shouldThrowOnListGrantsWithNullUserId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'user id' cannot be null!"); - api.grants().list(null); - } - - @Test - public void shouldReturnEmptyGrants() throws Exception { - @SuppressWarnings("deprecation") - Request> request = api.grants().list("userId"); - assertThat(request, is(notNullValue())); - - server.jsonResponse(MGMT_EMPTY_LIST, 200); - List response = request.execute(); - - assertThat(response, is(notNullValue())); - assertThat(response, is(emptyCollectionOf(Grant.class))); - } - @Test public void shouldThrowOnDeleteGrantWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'grant id' cannot be null!"); - api.grants().delete(null); + verifyThrows(IllegalArgumentException.class, + () -> api.grants().delete(null), + "'grant id' cannot be null!"); } @Test @@ -171,19 +122,19 @@ public void shouldDeleteGrantById() throws Exception { assertThat(request, is(notNullValue())); server.emptyResponse(200); - request.execute(); + request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("DELETE", "/api/v2/grants/1")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/grants/1")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); } @Test public void shouldThrowOnDeleteAllGrantsWithNullUserId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'user id' cannot be null!"); - api.grants().deleteAll(null); + verifyThrows(IllegalArgumentException.class, + () -> api.grants().deleteAll(null), + "'user id' cannot be null!"); } @Test @@ -192,10 +143,10 @@ public void shouldDeleteAllGrantsByUserId() throws Exception { assertThat(request, is(notNullValue())); server.emptyResponse(200); - request.execute(); + request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("DELETE", "/api/v2/grants")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/grants")); assertThat(recordedRequest, hasQueryParameter("user_id", "userId")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); diff --git a/src/test/java/com/auth0/client/mgmt/GuardianEntityTest.java b/src/test/java/com/auth0/client/mgmt/GuardianEntityTest.java index 84a0e70d3..4fe883277 100644 --- a/src/test/java/com/auth0/client/mgmt/GuardianEntityTest.java +++ b/src/test/java/com/auth0/client/mgmt/GuardianEntityTest.java @@ -2,27 +2,28 @@ import com.auth0.json.mgmt.guardian.*; import com.auth0.net.Request; -import java.util.Arrays; -import java.util.Collections; +import com.auth0.net.client.HttpMethod; import okhttp3.mockwebserver.RecordedRequest; -import org.junit.Test; +import org.junit.jupiter.api.Test; +import java.util.Collections; import java.util.List; import java.util.Map; +import static com.auth0.AssertsUtil.verifyThrows; import static com.auth0.client.MockServer.*; import static com.auth0.client.RecordedRequestMatcher.hasHeader; import static com.auth0.client.RecordedRequestMatcher.hasMethodAndPath; -import static org.hamcrest.Matchers.*; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; public class GuardianEntityTest extends BaseMgmtEntityTest { @Test public void shouldThrowOnDeleteGuardianEnrollmentWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'enrollment id' cannot be null!"); - api.guardian().deleteEnrollment(null); + verifyThrows(IllegalArgumentException.class, + () -> api.guardian().deleteEnrollment(null), + "'enrollment id' cannot be null!"); } @Test @@ -31,19 +32,19 @@ public void shouldDeleteGuardianEnrollment() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_GUARDIAN_ENROLLMENT, 200); - request.execute(); + request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("DELETE", "/api/v2/guardian/enrollments/1")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/guardian/enrollments/1")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); } @Test public void shouldThrowOnCreateGuardianEnrollmentTicketWithNullData() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'enrollment ticket' cannot be null!"); - api.guardian().createEnrollmentTicket(null); + verifyThrows(IllegalArgumentException.class, + () -> api.guardian().createEnrollmentTicket(null), + "'enrollment ticket' cannot be null!"); } @Test @@ -52,10 +53,10 @@ public void shouldCreateGuardianEnrollmentTicket() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_GUARDIAN_ENROLLMENT_TICKET, 200); - EnrollmentTicket response = request.execute(); + EnrollmentTicket response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/api/v2/guardian/enrollments/ticket")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/guardian/enrollments/ticket")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -72,10 +73,10 @@ public void shouldGetGuardianTemplates() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_GUARDIAN_TEMPLATES, 200); - GuardianTemplates response = request.execute(); + GuardianTemplates response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/guardian/factors/sms/templates")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/guardian/factors/sms/templates")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -84,9 +85,9 @@ public void shouldGetGuardianTemplates() throws Exception { @Test public void shouldThrowOnUpdateGuardianTemplatesWithNullData() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'guardian templates' cannot be null!"); - api.guardian().updateTemplates(null); + verifyThrows(IllegalArgumentException.class, + () -> api.guardian().updateTemplates(null), + "'guardian templates' cannot be null!"); } @Test @@ -95,10 +96,10 @@ public void shouldUpdateGuardianTemplates() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_GUARDIAN_TEMPLATES, 200); - GuardianTemplates response = request.execute(); + GuardianTemplates response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("PUT", "/api/v2/guardian/factors/sms/templates")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PUT, "/api/v2/guardian/factors/sms/templates")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -111,10 +112,10 @@ public void shouldListGuardianFactors() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_GUARDIAN_FACTORS_LIST, 200); - List response = request.execute(); + List response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/guardian/factors")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/guardian/factors")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -128,7 +129,7 @@ public void shouldReturnEmptyGuardianFactors() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_EMPTY_LIST, 200); - List response = request.execute(); + List response = request.execute().getBody(); assertThat(response, is(notNullValue())); assertThat(response, is(emptyCollectionOf(Factor.class))); @@ -136,16 +137,16 @@ public void shouldReturnEmptyGuardianFactors() throws Exception { @Test public void shouldThrowOnUpdateGuardianFactorWithNullName() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'name' cannot be null!"); - api.guardian().updateFactor(null, true); + verifyThrows(IllegalArgumentException.class, + () -> api.guardian().updateFactor(null, true), + "'name' cannot be null!"); } @Test public void shouldThrowOnUpdateGuardianFactorWithNullEnabled() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'enabled' cannot be null!"); - api.guardian().updateFactor("my-factor", null); + verifyThrows(IllegalArgumentException.class, + () -> api.guardian().updateFactor("my-factor", null), + "'enabled' cannot be null!"); } @Test @@ -154,10 +155,10 @@ public void shouldUpdateGuardianFactor() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_GUARDIAN_FACTOR, 200); - Factor response = request.execute(); + Factor response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("PUT", "/api/v2/guardian/factors/my-factor")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PUT, "/api/v2/guardian/factors/my-factor")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -174,10 +175,10 @@ public void shouldGetGuardianTwilioFactorProviderWithMSSID() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_GUARDIAN_TWILIO_FACTOR_PROVIDER_WITH_MSSID, 200); - TwilioFactorProvider response = request.execute(); + TwilioFactorProvider response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/guardian/factors/sms/providers/twilio")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/guardian/factors/sms/providers/twilio")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -190,10 +191,10 @@ public void shouldGetGuardianTwilioFactorProviderWithFrom() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_GUARDIAN_TWILIO_FACTOR_PROVIDER_WITH_FROM, 200); - TwilioFactorProvider response = request.execute(); + TwilioFactorProvider response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/guardian/factors/sms/providers/twilio")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/guardian/factors/sms/providers/twilio")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -202,9 +203,9 @@ public void shouldGetGuardianTwilioFactorProviderWithFrom() throws Exception { @Test public void shouldThrowOnUpdateGuardianTwilioFactorProviderWithNullData() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'provider' cannot be null!"); - api.guardian().updateTwilioFactorProvider(null); + verifyThrows(IllegalArgumentException.class, + () -> api.guardian().updateTwilioFactorProvider(null), + "'provider' cannot be null!"); } @Test @@ -214,10 +215,10 @@ public void shouldUpdateGuardianTwilioFactorProviderWithFrom() throws Exception assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_GUARDIAN_TWILIO_FACTOR_PROVIDER_WITH_FROM, 200); - TwilioFactorProvider response = request.execute(); + TwilioFactorProvider response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("PUT", "/api/v2/guardian/factors/sms/providers/twilio")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PUT, "/api/v2/guardian/factors/sms/providers/twilio")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -241,10 +242,10 @@ public void shouldUpdateGuardianTwilioFactorProviderWithMSSID() throws Exception assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_GUARDIAN_TWILIO_FACTOR_PROVIDER_WITH_MSSID, 200); - TwilioFactorProvider response = request.execute(); + TwilioFactorProvider response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("PUT", "/api/v2/guardian/factors/sms/providers/twilio")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PUT, "/api/v2/guardian/factors/sms/providers/twilio")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -267,10 +268,10 @@ public void shouldResetGuardianTwilioFactorProvider() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_GUARDIAN_TWILIO_FACTOR_PROVIDER_EMPTY, 200); - TwilioFactorProvider response = request.execute(); + TwilioFactorProvider response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("PUT", "/api/v2/guardian/factors/sms/providers/twilio")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PUT, "/api/v2/guardian/factors/sms/providers/twilio")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -290,10 +291,10 @@ public void shouldGetGuardianSnsFactorProvider() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_GUARDIAN_SNS_FACTOR_PROVIDER, 200); - SNSFactorProvider response = request.execute(); + SNSFactorProvider response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/guardian/factors/push-notification/providers/sns")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/guardian/factors/push-notification/providers/sns")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -302,9 +303,9 @@ public void shouldGetGuardianSnsFactorProvider() throws Exception { @Test public void shouldThrowOnUpdateGuardianSnsFactorProviderWithNullData() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'provider' cannot be null!"); - api.guardian().updateSNSFactorProvider(null); + verifyThrows(IllegalArgumentException.class, + () -> api.guardian().updateSNSFactorProvider(null), + "'provider' cannot be null!"); } @Test @@ -314,10 +315,10 @@ public void shouldUpdateGuardianSnsFactorProvider() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_GUARDIAN_SNS_FACTOR_PROVIDER, 200); - SNSFactorProvider response = request.execute(); + SNSFactorProvider response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("PUT", "/api/v2/guardian/factors/push-notification/providers/sns")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PUT, "/api/v2/guardian/factors/push-notification/providers/sns")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -338,10 +339,10 @@ public void shouldResetGuardianSnsFactorProvider() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_GUARDIAN_SNS_FACTOR_PROVIDER_EMPTY, 200); - SNSFactorProvider response = request.execute(); + SNSFactorProvider response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("PUT", "/api/v2/guardian/factors/push-notification/providers/sns")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PUT, "/api/v2/guardian/factors/push-notification/providers/sns")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -362,10 +363,10 @@ public void shouldGetAuthenticationPolicies() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_GUARDIAN_AUTHENTICATION_POLICIES_LIST, 200); - List response = request.execute(); + List response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/guardian/policies")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/guardian/policies")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -374,9 +375,9 @@ public void shouldGetAuthenticationPolicies() throws Exception { @Test public void shouldThrowOnUpdateAuthenticationPoliciesWithNullData() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'policies' cannot be null!"); - api.guardian().updateAuthenticationPolicies(null); + verifyThrows(IllegalArgumentException.class, + () -> api.guardian().updateAuthenticationPolicies(null), + "'policies' cannot be null!"); } @Test @@ -386,10 +387,10 @@ public void shouldUpdateAuthenticationPolicies() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_GUARDIAN_AUTHENTICATION_POLICIES_LIST, 200); - List response = request.execute(); + List response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("PUT", "/api/v2/guardian/policies")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PUT, "/api/v2/guardian/policies")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); diff --git a/src/test/java/com/auth0/client/mgmt/JobsEntityTest.java b/src/test/java/com/auth0/client/mgmt/JobsEntityTest.java index ea281dda3..5087b5098 100644 --- a/src/test/java/com/auth0/client/mgmt/JobsEntityTest.java +++ b/src/test/java/com/auth0/client/mgmt/JobsEntityTest.java @@ -2,16 +2,17 @@ import com.auth0.client.mgmt.filter.UsersExportFilter; import com.auth0.client.mgmt.filter.UsersImportOptions; -import com.auth0.json.mgmt.EmailVerificationIdentity; import com.auth0.json.mgmt.jobs.Job; import com.auth0.json.mgmt.jobs.JobErrorDetails; import com.auth0.json.mgmt.jobs.UsersExportField; +import com.auth0.json.mgmt.tickets.EmailVerificationIdentity; import com.auth0.net.Request; -import com.auth0.net.multipart.FilePart; -import com.auth0.net.multipart.KeyValuePart; -import com.auth0.net.multipart.RecordedMultipartRequest; +import com.auth0.net.client.HttpMethod; +import com.auth0.net.client.multipart.FilePart; +import com.auth0.net.client.multipart.KeyValuePart; +import com.auth0.net.client.multipart.RecordedMultipartRequest; import okhttp3.mockwebserver.RecordedRequest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.io.File; import java.nio.file.Files; @@ -20,14 +21,15 @@ import java.util.List; import java.util.Map; +import static com.auth0.AssertsUtil.verifyThrows; import static com.auth0.client.MockServer.*; import static com.auth0.client.RecordedRequestMatcher.hasHeader; import static com.auth0.client.RecordedRequestMatcher.hasMethodAndPath; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNull.notNullValue; import static org.hamcrest.core.IsNull.nullValue; -import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -35,9 +37,9 @@ public class JobsEntityTest extends BaseMgmtEntityTest { @Test public void shouldThrowOnGetJobWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'job id' cannot be null!"); - api.jobs().get(null); + verifyThrows(IllegalArgumentException.class, + () -> api.jobs().get(null), + "'job id' cannot be null!"); } @Test @@ -46,10 +48,10 @@ public void shouldGetJob() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_JOB, 200); - Job response = request.execute(); + Job response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/jobs/1")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/jobs/1")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -58,9 +60,9 @@ public void shouldGetJob() throws Exception { @Test public void shouldThrowOnGetJobErrorDetailsWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'job id' cannot be null!"); - api.jobs().getErrorDetails(null); + verifyThrows(IllegalArgumentException.class, + () -> api.jobs().getErrorDetails(null), + "'job id' cannot be null!"); } @Test @@ -69,10 +71,10 @@ public void shouldGetJobErrorDetails() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_JOB_ERROR_DETAILS, 200); - List response = request.execute(); + List response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/jobs/1/errors")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/jobs/1/errors")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -87,10 +89,10 @@ public void shouldGetJobErrorDetails_noErrors() throws Exception { assertThat(request, is(notNullValue())); server.noContentResponse(); - List response = request.execute(); + List response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/jobs/1/errors")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/jobs/1/errors")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -99,27 +101,30 @@ public void shouldGetJobErrorDetails_noErrors() throws Exception { } @Test + @SuppressWarnings("deprecation") public void shouldThrowOnRequestUsersExportWithNullConnectionId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'connection id' cannot be null!"); - api.jobs().exportUsers(null, null); + verifyThrows(IllegalArgumentException.class, + () -> api.jobs().exportUsers(null, null), + "'connection id' cannot be null!"); } @Test + @SuppressWarnings("deprecation") public void shouldNotThrowOnRequestUsersExportWithNullFilter() { api.jobs().exportUsers("con_123456789", null); } @Test + @SuppressWarnings("deprecation") public void shouldRequestUsersExport() throws Exception { Request request = api.jobs().exportUsers("con_123456789", null); assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_JOB_POST_USERS_EXPORTS, 200); - Job response = request.execute(); + Job response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/api/v2/jobs/users-exports")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/jobs/users-exports")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -131,6 +136,105 @@ public void shouldRequestUsersExport() throws Exception { } @Test + @SuppressWarnings("deprecation") + public void usersExportWithFilterOverridesClientId() throws Exception { + UsersExportFilter filter = new UsersExportFilter(); + filter.withConnectionId("filter_con"); + + Request request = api.jobs().exportUsers("con_123456789", filter); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_JOB_POST_USERS_EXPORTS, 200); + Job response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/jobs/users-exports")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + Map body = bodyFromRequest(recordedRequest); + assertThat(body.size(), is(1)); + assertThat(body, hasEntry("connection_id", "filter_con")); + + assertThat(response, is(notNullValue())); + } + + @Test + public void shouldRequestUsersExportWithoutConnectionOrFilter() throws Exception { + Request request = api.jobs().exportUsers(null); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_JOB_POST_USERS_EXPORTS, 200); + Job response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/jobs/users-exports")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + Map body = bodyFromRequest(recordedRequest); + assertThat(body.size(), is(0)); + + assertThat(response, is(notNullValue())); + } + + @Test + public void shouldRequestUsersExportWithFilter() throws Exception { + UsersExportFilter filter = new UsersExportFilter(); + filter.withConnectionId("conId"); + filter.withFormat("json"); + List fields = new ArrayList<>(); + fields.add(new UsersExportField("full_name")); + fields.add(new UsersExportField("user_metadata.company_name", "company")); + filter.withFields(fields); + + Request request = api.jobs().exportUsers(filter); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_JOB_POST_USERS_EXPORTS, 200); + Job response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/jobs/users-exports")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + Map body = bodyFromRequest(recordedRequest); + assertThat(body.size(), is(3)); + assertThat(body, hasEntry("connection_id", "conId")); + assertThat(body, hasEntry("format", "json")); + assertThat(body, hasKey("fields")); + @SuppressWarnings("unchecked") + List> bodyFields = (List>) body.get("fields"); + assertThat(bodyFields.get(0).get("name"), is("full_name")); + assertThat(bodyFields.get(0).get("export_as"), is(nullValue())); + assertThat(bodyFields.get(1).get("name"), is("user_metadata.company_name")); + assertThat(bodyFields.get(1).get("export_as"), is("company")); + + assertThat(response, is(notNullValue())); + } + + @Test + public void usersExportShouldHandleNullFilter() throws Exception { + Request request = api.jobs().exportUsers(null); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_JOB_POST_USERS_EXPORTS, 200); + Job response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/jobs/users-exports")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + Map body = bodyFromRequest(recordedRequest); + assertThat(body.size(), is(0)); + + assertThat(response, is(notNullValue())); + } + + @Test + @SuppressWarnings("deprecation") public void shouldRequestUsersExportWithLimit() throws Exception { UsersExportFilter filter = new UsersExportFilter(); filter.withLimit(82); @@ -138,10 +242,10 @@ public void shouldRequestUsersExportWithLimit() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_JOB_POST_USERS_EXPORTS, 200); - Job response = request.execute(); + Job response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/api/v2/jobs/users-exports")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/jobs/users-exports")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -154,6 +258,7 @@ public void shouldRequestUsersExportWithLimit() throws Exception { } @Test + @SuppressWarnings("deprecation") public void shouldRequestUsersExportWithFormat() throws Exception { UsersExportFilter filter = new UsersExportFilter(); filter.withFormat("csv"); @@ -161,10 +266,10 @@ public void shouldRequestUsersExportWithFormat() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_JOB_POST_USERS_EXPORTS, 200); - Job response = request.execute(); + Job response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/api/v2/jobs/users-exports")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/jobs/users-exports")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -177,6 +282,7 @@ public void shouldRequestUsersExportWithFormat() throws Exception { } @Test + @SuppressWarnings("deprecation") public void shouldRequestUsersExportWithFields() throws Exception { UsersExportFilter filter = new UsersExportFilter(); ArrayList fields = new ArrayList<>(); @@ -187,10 +293,10 @@ public void shouldRequestUsersExportWithFields() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_JOB_POST_USERS_EXPORTS, 200); - Job response = request.execute(); + Job response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/api/v2/jobs/users-exports")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/jobs/users-exports")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -214,10 +320,10 @@ public void shouldSendUserAVerificationEmailWithNullClientIdAndEmailVerification assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_JOB_POST_VERIFICATION_EMAIL, 200); - Job response = request.execute(); + Job response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/api/v2/jobs/verification-email")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/jobs/verification-email")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -234,10 +340,10 @@ public void shouldSendUserVerificationEmailWithClientId() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_JOB_POST_VERIFICATION_EMAIL, 200); - Job response = request.execute(); + Job response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/api/v2/jobs/verification-email")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/jobs/verification-email")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -256,10 +362,10 @@ public void shouldSendUserVerificationEmailWithIdentity() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_JOB_POST_VERIFICATION_EMAIL, 200); - Job response = request.execute(); + Job response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/api/v2/jobs/verification-email")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/jobs/verification-email")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -282,10 +388,10 @@ public void shouldSendUserVerificationEmailWithOrgId() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_JOB_POST_VERIFICATION_EMAIL, 200); - Job response = request.execute(); + Job response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/api/v2/jobs/verification-email")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/jobs/verification-email")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -300,41 +406,41 @@ public void shouldSendUserVerificationEmailWithOrgId() throws Exception { @Test public void shouldThrowOnSendUserVerificationEmailWithNullIdentityProvider() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'identity provider' cannot be null!"); - api.jobs().sendVerificationEmail("google-oauth2|1234", null, new EmailVerificationIdentity(null, "user-id")); + verifyThrows(IllegalArgumentException.class, + () -> api.jobs().sendVerificationEmail("google-oauth2|1234", null, new EmailVerificationIdentity(null, "user-id")), + "'identity provider' cannot be null!"); } @Test public void shouldThrowOnSendUserVerificationEmailWithNullIdentityUserId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'identity user id' cannot be null!"); - api.jobs().sendVerificationEmail("google-oauth2|1234", null, new EmailVerificationIdentity("google-oauth2", null)); + verifyThrows(IllegalArgumentException.class, + () -> api.jobs().sendVerificationEmail("google-oauth2|1234", null, new EmailVerificationIdentity("google-oauth2", null)), + "'identity user id' cannot be null!"); } @Test public void shouldThrowOnSendUserVerificationEmailWithNullIdentityProviderAndUserId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'identity provider' cannot be null!"); - api.jobs().sendVerificationEmail("google-oauth2|1234", null, new EmailVerificationIdentity(null, null)); + verifyThrows(IllegalArgumentException.class, + () -> api.jobs().sendVerificationEmail("google-oauth2|1234", null, new EmailVerificationIdentity(null, null)), + "'identity provider' cannot be null!"); } @Test public void shouldThrowOnRequestUsersImportWithNullConnectionId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'connection id' cannot be null!"); File usersFile = mock(File.class); when(usersFile.exists()).thenReturn(true); UsersImportOptions options = mock(UsersImportOptions.class); - api.jobs().importUsers(null, usersFile, options); + verifyThrows(IllegalArgumentException.class, + () -> api.jobs().importUsers(null, usersFile, options), + "'connection id' cannot be null!"); } @Test public void shouldThrowOnRequestUsersImportWithNullUsersFile() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'users file' cannot be null!"); UsersImportOptions options = mock(UsersImportOptions.class); - api.jobs().importUsers("con_123456789", null, options); + verifyThrows(IllegalArgumentException.class, + () -> api.jobs().importUsers("con_123456789", null, options), + "'users file' cannot be null!"); } @Test @@ -351,10 +457,10 @@ public void shouldRequestUsersImport() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_JOB_POST_USERS_IMPORTS, 200); - Job response = request.execute(); + Job response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/api/v2/jobs/users-imports")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/jobs/users-imports")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); String ctHeader = recordedRequest.getHeader("Content-Type"); assertThat(ctHeader, startsWith("multipart/form-data")); @@ -392,10 +498,10 @@ public void shouldRequestUsersImportWithOptions() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_JOB_POST_USERS_IMPORTS, 200); - Job response = request.execute(); + Job response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/api/v2/jobs/users-imports")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/jobs/users-imports")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); String ctHeader = recordedRequest.getHeader("Content-Type"); assertThat(ctHeader, startsWith("multipart/form-data")); @@ -436,5 +542,4 @@ public void shouldRequestUsersImportWithOptions() throws Exception { assertThat(response, is(notNullValue())); } - } diff --git a/src/test/java/com/auth0/client/mgmt/KeysEntityTest.java b/src/test/java/com/auth0/client/mgmt/KeysEntityTest.java index d02dff5ac..98d54dcb5 100644 --- a/src/test/java/com/auth0/client/mgmt/KeysEntityTest.java +++ b/src/test/java/com/auth0/client/mgmt/KeysEntityTest.java @@ -1,12 +1,19 @@ package com.auth0.client.mgmt; -import com.auth0.json.mgmt.Key; +import com.auth0.client.mgmt.filter.EncryptionKeyFilter; +import com.auth0.json.mgmt.keys.EncryptionKey; +import com.auth0.json.mgmt.keys.EncryptionKeysPage; +import com.auth0.json.mgmt.keys.EncryptionWrappingKeyResponse; +import com.auth0.json.mgmt.keys.Key; import com.auth0.net.Request; +import com.auth0.net.client.HttpMethod; import okhttp3.mockwebserver.RecordedRequest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.List; +import java.util.Map; +import static com.auth0.AssertsUtil.verifyThrows; import static com.auth0.client.MockServer.*; import static com.auth0.client.RecordedRequestMatcher.*; import static org.hamcrest.MatcherAssert.assertThat; @@ -16,16 +23,16 @@ public class KeysEntityTest extends BaseMgmtEntityTest { @Test public void shouldThrowOnGetWithIdNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'kid' cannot be null!"); - api.keys().get(null); + verifyThrows(IllegalArgumentException.class, + () -> api.keys().get(null), + "'kid' cannot be null!"); } @Test public void shouldThrowOnRevokeWithIdNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'kid' cannot be null!"); - api.keys().revoke(null); + verifyThrows(IllegalArgumentException.class, + () -> api.keys().revoke(null), + "'kid' cannot be null!"); } @Test @@ -34,10 +41,10 @@ public void shouldListKeys() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(KEY_LIST, 200); - List response = request.execute(); + List response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/keys/signing")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/keys/signing")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -51,10 +58,10 @@ public void shouldGetKeyWithId() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(KEY, 200); - Key response = request.execute(); + Key response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/keys/signing/123")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/keys/signing/123")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -67,10 +74,10 @@ public void shouldRotateKey() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(KEY_ROTATE, 200); - Key response = request.execute(); + Key response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/api/v2/keys/signing/rotate")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/keys/signing/rotate")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -83,13 +90,176 @@ public void shouldRevokeKey() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(KEY_REVOKE, 200); - Key response = request.execute(); + Key response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("PUT", "/api/v2/keys/signing/123/revoke")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PUT, "/api/v2/keys/signing/123/revoke")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(response, is(notNullValue())); } + + @Test + public void shouldRekey() throws Exception { + Request request = api.keys().postEncryptionRekey(); + assertThat(request, is(notNullValue())); + + server.emptyResponse(204); + request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/keys/encryption/rekey")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + } + + @Test + public void shouldListEncryptionKeysWithoutFilter() throws Exception { + Request request = api.keys().listEncryptionKeys(null); + assertThat(request, is(notNullValue())); + + server.jsonResponse(ENCRYPTION_KEYS_LIST, 200); + EncryptionKeysPage response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/keys/encryption")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + assertThat(response, is(notNullValue())); + assertThat(response.getItems(), hasSize(3)); + } + + @Test + public void shouldListEncryptionKeysWithPage() throws Exception { + EncryptionKeyFilter filter = new EncryptionKeyFilter().withPage(1, 5); + Request request = api.keys().listEncryptionKeys(filter); + assertThat(request, is(notNullValue())); + + server.jsonResponse(ENCRYPTION_KEYS_LIST, 200); + EncryptionKeysPage response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/keys/encryption")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + assertThat(recordedRequest, hasQueryParameter("page", "1")); + assertThat(recordedRequest, hasQueryParameter("per_page", "5")); + + assertThat(response, is(notNullValue())); + assertThat(response.getItems(), hasSize(3)); + } + + @Test + public void shouldListEncryptionKeysWithTotals() throws Exception { + EncryptionKeyFilter filter = new EncryptionKeyFilter().withTotals(true); + Request request = api.keys().listEncryptionKeys(filter); + assertThat(request, is(notNullValue())); + + server.jsonResponse(ENCRYPTION_KEYS_LIST, 200); + EncryptionKeysPage response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/keys/encryption")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + assertThat(recordedRequest, hasQueryParameter("include_totals", "true")); + + assertThat(response, is(notNullValue())); + assertThat(response.getItems(), hasSize(3)); + } + + @Test + public void shouldGetEncryptionKeyWithKid() throws Exception { + Request request = api.keys().getEncryptionKey("123"); + assertThat(request, is(notNullValue())); + + server.jsonResponse(ENCRYPTION_KEY, 200); + EncryptionKey response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/keys/encryption/123")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + assertThat(response, is(notNullValue())); + } + + @Test + public void shouldCreateEncryptionKey() throws Exception { + Request request = api.keys().createEncryptionKey("tenant-master-key"); + assertThat(request, is(notNullValue())); + + server.jsonResponse(ENCRYPTION_KEY, 201); + EncryptionKey response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/keys/encryption")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + Map body = bodyFromRequest(recordedRequest); + assertThat(body.size(), is(1)); + assertThat(body, hasEntry("type", "tenant-master-key")); + + assertThat(response, is(notNullValue())); + } + + @Test + public void shouldImportEncryptionKey() throws Exception { + Request request = api.keys().importEncryptionKey("key@1234", "123"); + assertThat(request, is(notNullValue())); + + server.jsonResponse(ENCRYPTION_KEY, 201); + EncryptionKey response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/keys/encryption/123")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + Map body = bodyFromRequest(recordedRequest); + assertThat(body.size(), is(1)); + assertThat(body, hasEntry("wrapped_key", "key@1234")); + + assertThat(response, is(notNullValue())); + } + + @Test + public void shouldCreateEncryptionWrappingKey() throws Exception { + Request request = api.keys().createEncryptionWrappingKey("123"); + assertThat(request, is(notNullValue())); + + server.jsonResponse(ENCRYPTION_KEY, 201); + EncryptionWrappingKeyResponse response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/keys/encryption/123/wrapping-key")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + assertThat(response, is(notNullValue())); + } + + @Test + public void shouldDeleteEncryptionKey() throws Exception { + Request request = api.keys().deleteEncryptionKey("123"); + assertThat(request, is(notNullValue())); + + server.jsonResponse(ENCRYPTION_KEY, 200); + request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/keys/encryption/123")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + } + + @Test + public void shouldThrowOnDeleteEncryptionKeyWithNullKid(){ + verifyThrows(IllegalArgumentException.class, + () -> api.keys().deleteEncryptionKey(null), + "'kid' cannot be null!"); + } } diff --git a/src/test/java/com/auth0/client/mgmt/LogEventsEntityTest.java b/src/test/java/com/auth0/client/mgmt/LogEventsEntityTest.java index dade5b059..d6a502873 100644 --- a/src/test/java/com/auth0/client/mgmt/LogEventsEntityTest.java +++ b/src/test/java/com/auth0/client/mgmt/LogEventsEntityTest.java @@ -4,13 +4,15 @@ import com.auth0.json.mgmt.logevents.LogEvent; import com.auth0.json.mgmt.logevents.LogEventsPage; import com.auth0.net.Request; +import com.auth0.net.client.HttpMethod; import okhttp3.mockwebserver.RecordedRequest; -import org.junit.Test; +import org.junit.jupiter.api.Test; +import static com.auth0.AssertsUtil.verifyThrows; import static com.auth0.client.MockServer.*; import static com.auth0.client.RecordedRequestMatcher.*; -import static org.hamcrest.Matchers.*; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; public class LogEventsEntityTest extends BaseMgmtEntityTest { @@ -20,10 +22,10 @@ public void shouldListEventLogs() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_LOG_EVENTS_LIST, 200); - LogEventsPage response = request.execute(); + LogEventsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/logs")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/logs")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -38,10 +40,10 @@ public void shouldListLogEventsWithPage() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_LOG_EVENTS_LIST, 200); - LogEventsPage response = request.execute(); + LogEventsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/logs")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/logs")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("page", "23")); @@ -58,10 +60,10 @@ public void shouldListLogEventsWithTotals() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_LOG_EVENTS_PAGED_LIST, 200); - LogEventsPage response = request.execute(); + LogEventsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/logs")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/logs")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("include_totals", "true")); @@ -81,10 +83,10 @@ public void shouldListLogEventsWithSort() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_LOG_EVENTS_LIST, 200); - LogEventsPage response = request.execute(); + LogEventsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/logs")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/logs")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("sort", "date:1")); @@ -100,10 +102,10 @@ public void shouldListLogEventsWithQuery() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_LOG_EVENTS_LIST, 200); - LogEventsPage response = request.execute(); + LogEventsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/logs")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/logs")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("q", "email:\\*@gmail.com")); @@ -119,10 +121,10 @@ public void shouldListLogEventsWithCheckpoint() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_LOG_EVENTS_LIST, 200); - LogEventsPage response = request.execute(); + LogEventsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/logs")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/logs")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("from", "id3")); @@ -139,10 +141,10 @@ public void shouldListLogEventsWithFields() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_LOG_EVENTS_LIST, 200); - LogEventsPage response = request.execute(); + LogEventsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/logs")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/logs")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("fields", "some,random,fields")); @@ -158,7 +160,7 @@ public void shouldReturnEmptyLogEvents() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_EMPTY_LIST, 200); - LogEventsPage response = request.execute(); + LogEventsPage response = request.execute().getBody(); assertThat(response, is(notNullValue())); assertThat(response.getItems(), is(emptyCollectionOf(LogEvent.class))); @@ -166,9 +168,9 @@ public void shouldReturnEmptyLogEvents() throws Exception { @Test public void shouldThrowOnGetLogEventWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'log event id' cannot be null!"); - api.logEvents().get(null); + verifyThrows(IllegalArgumentException.class, + () -> api.logEvents().get(null), + "'log event id' cannot be null!"); } @Test @@ -177,10 +179,10 @@ public void shouldGetLogEvent() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_LOG_EVENT, 200); - LogEvent response = request.execute(); + LogEvent response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/logs/1")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/logs/1")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); diff --git a/src/test/java/com/auth0/client/mgmt/LogStreamsEntityTest.java b/src/test/java/com/auth0/client/mgmt/LogStreamsEntityTest.java index b7394aac6..f92e95a11 100644 --- a/src/test/java/com/auth0/client/mgmt/LogStreamsEntityTest.java +++ b/src/test/java/com/auth0/client/mgmt/LogStreamsEntityTest.java @@ -2,19 +2,23 @@ import com.auth0.client.MockServer; import com.auth0.json.mgmt.logstreams.LogStream; +import com.auth0.json.mgmt.logstreams.LogStreamFilter; import com.auth0.net.Request; +import com.auth0.net.client.HttpMethod; import okhttp3.mockwebserver.RecordedRequest; -import org.junit.Test; +import org.junit.jupiter.api.Test; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import static com.auth0.AssertsUtil.verifyThrows; import static com.auth0.client.MockServer.*; import static com.auth0.client.RecordedRequestMatcher.hasHeader; import static com.auth0.client.RecordedRequestMatcher.hasMethodAndPath; -import static org.hamcrest.Matchers.*; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; public class LogStreamsEntityTest extends BaseMgmtEntityTest { @@ -24,10 +28,10 @@ public void shouldListLogStreams() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MockServer.MGMT_LOG_STREAMS_LIST, 200); - List response = request.execute(); + List response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/log-streams")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/log-streams")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -38,6 +42,7 @@ public void shouldListLogStreams() throws Exception { assertThat(response, everyItem(hasProperty("type", is(notNullValue())))); assertThat(response, everyItem(hasProperty("status", is(notNullValue())))); assertThat(response, everyItem(hasProperty("sink", is(notNullValue())))); + assertThat(response, everyItem(hasProperty("filters", is(notNullValue())))); } @Test @@ -46,7 +51,7 @@ public void shouldReturnEmptyLogStreams() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_EMPTY_LIST, 200); - List response = request.execute(); + List response = request.execute().getBody(); assertThat(response, is(notNullValue())); assertThat(response, empty()); @@ -58,10 +63,10 @@ public void shouldGetLogStream() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MockServer.MGMT_LOG_STREAM, 200); - LogStream response = request.execute(); + LogStream response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/log-streams/123")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/log-streams/123")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -71,28 +76,33 @@ public void shouldGetLogStream() throws Exception { assertThat(response, hasProperty("type", is(notNullValue()))); assertThat(response, hasProperty("status", is(notNullValue()))); assertThat(response, hasProperty("sink", is(notNullValue()))); + assertThat(response, hasProperty("filters", is(notNullValue()))); } @Test public void shouldCreateLogStream() throws Exception { LogStream logStream = getLogStream("log stream", "http"); + LogStreamFilter filter = new LogStreamFilter("category", "auth.ancillary.success"); + logStream.setFilters(Collections.singletonList(filter)); Request request = api.logStreams().create(logStream); assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_LOG_STREAM, 200); - LogStream response = request.execute(); + LogStream response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/api/v2/log-streams")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/log-streams")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); Map body = bodyFromRequest(recordedRequest); - assertThat(body.size(), is(3)); + assertThat(body.size(), is(4)); assertThat(body, hasEntry("name", "log stream")); assertThat(body, hasEntry("type", "http")); assertThat(body, hasEntry("sink", logStream.getSink())); + assertThat(body, hasKey("filters")); + assertThat(body.get("filters"), is(notNullValue())); assertThat(response, is(notNullValue())); assertThat(response, hasProperty("id", is(notNullValue()))); @@ -100,6 +110,7 @@ public void shouldCreateLogStream() throws Exception { assertThat(response, hasProperty("type", is(notNullValue()))); assertThat(response, hasProperty("status", is(notNullValue()))); assertThat(response, hasProperty("sink", is(notNullValue()))); + assertThat(response, hasProperty("filters", is(notNullValue()))); } @@ -112,10 +123,10 @@ public void shouldUpdateLogStream() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_LOG_STREAM, 200); - LogStream response = request.execute(); + LogStream response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("PATCH", "/api/v2/log-streams/123")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PATCH, "/api/v2/log-streams/123")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -139,47 +150,47 @@ public void shouldDeleteLogStream() throws Exception { assertThat(request, is(notNullValue())); server.emptyResponse(204); - request.execute(); + request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("DELETE", "/api/v2/log-streams/1")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/log-streams/1")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); } @Test public void shouldThrowOnGetLogStreamWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'log stream id' cannot be null!"); - api.logStreams().get(null); + verifyThrows(IllegalArgumentException.class, + () -> api.logStreams().get(null), + "'log stream id' cannot be null!"); } @Test public void shouldThrowOnDeleteLogStreamWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'log stream id' cannot be null!"); - api.logStreams().delete(null); + verifyThrows(IllegalArgumentException.class, + () -> api.logStreams().delete(null), + "'log stream id' cannot be null!"); } @Test public void shouldThrowOnUpdateLogStreamWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'log stream id' cannot be null!"); - api.logStreams().update(null, new LogStream()); + verifyThrows(IllegalArgumentException.class, + () -> api.logStreams().update(null, new LogStream()), + "'log stream id' cannot be null!"); } @Test public void shouldThrowOnUpdateLogStreamWithNullLogStream() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'log stream' cannot be null!"); - api.logStreams().update("123", null); + verifyThrows(IllegalArgumentException.class, + () -> api.logStreams().update("123", null), + "'log stream' cannot be null!"); } @Test public void shouldThrowOnCreateLogStreamWithNullLogStream() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'log stream' cannot be null!"); - api.logStreams().create(null); + verifyThrows(IllegalArgumentException.class, + () -> api.logStreams().create(null), + "'log stream' cannot be null!"); } private LogStream getLogStream(String name, String type) { diff --git a/src/test/java/com/auth0/client/mgmt/ManagementAPITest.java b/src/test/java/com/auth0/client/mgmt/ManagementAPITest.java index 7d9e4fbeb..419f8511a 100644 --- a/src/test/java/com/auth0/client/mgmt/ManagementAPITest.java +++ b/src/test/java/com/auth0/client/mgmt/ManagementAPITest.java @@ -1,29 +1,21 @@ package com.auth0.client.mgmt; -import com.auth0.client.HttpOptions; -import com.auth0.client.LoggingOptions; import com.auth0.client.MockServer; -import com.auth0.client.ProxyOptions; -import com.auth0.net.RateLimitInterceptor; -import com.auth0.net.Telemetry; -import com.auth0.net.TelemetryInterceptor; -import okhttp3.*; -import okhttp3.logging.HttpLoggingInterceptor; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.mockito.Mockito; - -import java.net.Proxy; -import java.util.HashSet; -import java.util.Set; +import com.auth0.exception.Auth0Exception; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.Auth0HttpRequest; +import com.auth0.net.client.Auth0HttpResponse; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import java.util.concurrent.CompletableFuture; + +import static com.auth0.AssertsUtil.verifyThrows; import static com.auth0.client.UrlMatcher.isUrl; -import static okhttp3.logging.HttpLoggingInterceptor.Level; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; public class ManagementAPITest { @@ -33,17 +25,13 @@ public class ManagementAPITest { private MockServer server; private ManagementAPI api; - @SuppressWarnings("deprecation") - @Rule - public ExpectedException exception = ExpectedException.none(); - - @Before + @BeforeEach public void setUp() throws Exception { server = new MockServer(); - api = new ManagementAPI(server.getBaseUrl(), API_TOKEN); + api = ManagementAPI.newBuilder(server.getBaseUrl(), API_TOKEN).build(); } - @After + @AfterEach public void tearDown() throws Exception { server.stop(); } @@ -52,505 +40,179 @@ public void tearDown() throws Exception { @Test public void shouldAcceptDomainWithNoScheme() { - ManagementAPI api = new ManagementAPI("me.something.com", API_TOKEN); + ManagementAPI api = ManagementAPI.newBuilder("me.something.com", API_TOKEN).build(); assertThat(api.getBaseUrl(), is(notNullValue())); assertThat(api.getBaseUrl().toString(), isUrl("https", "me.something.com")); } @Test - public void shouldAcceptDomainWithHttpScheme() { - ManagementAPI api = new ManagementAPI("http://me.something.com", API_TOKEN); - - assertThat(api.getBaseUrl(), is(notNullValue())); - assertThat(api.getBaseUrl().toString(), isUrl("http", "me.something.com")); - } - - @Test - public void shouldThrowWhenDomainIsInvalid() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("The domain had an invalid format and couldn't be parsed as an URL."); - new ManagementAPI("", API_TOKEN); - } - - @Test - public void shouldThrowWhenDomainIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'domain' cannot be null!"); - new ManagementAPI(null, API_TOKEN); - } - - @Test - public void shouldThrowWhenApiTokenIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'api token' cannot be null!"); - new ManagementAPI(DOMAIN, null); - } - - @Test - public void shouldThrowOnUpdateWhenApiTokenIsNull() { - ManagementAPI api = new ManagementAPI(DOMAIN, API_TOKEN); - - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'api token' cannot be null!"); - api.setApiToken(null); - } - - @Test - public void shouldUpdateApiToken() { - //Initialize with a token - ManagementAPI api = new ManagementAPI(DOMAIN, "first token"); - - assertThat(api.blacklists().apiToken, is("first token")); - assertThat(api.clientGrants().apiToken, is("first token")); - assertThat(api.clients().apiToken, is("first token")); - assertThat(api.connections().apiToken, is("first token")); - assertThat(api.deviceCredentials().apiToken, is("first token")); - assertThat(api.emailProvider().apiToken, is("first token")); - assertThat(api.emailTemplates().apiToken, is("first token")); - assertThat(api.grants().apiToken, is("first token")); - assertThat(api.guardian().apiToken, is("first token")); - assertThat(api.jobs().apiToken, is("first token")); - assertThat(api.logEvents().apiToken, is("first token")); - assertThat(api.resourceServers().apiToken, is("first token")); - assertThat(api.rules().apiToken, is("first token")); - assertThat(api.stats().apiToken, is("first token")); - assertThat(api.tenants().apiToken, is("first token")); - assertThat(api.tickets().apiToken, is("first token")); - assertThat(api.userBlocks().apiToken, is("first token")); - assertThat(api.users().apiToken, is("first token")); - - //Update the token - api.setApiToken("new token"); - - assertThat(api.blacklists().apiToken, is("new token")); - assertThat(api.clientGrants().apiToken, is("new token")); - assertThat(api.clients().apiToken, is("new token")); - assertThat(api.connections().apiToken, is("new token")); - assertThat(api.deviceCredentials().apiToken, is("new token")); - assertThat(api.emailProvider().apiToken, is("new token")); - assertThat(api.emailTemplates().apiToken, is("new token")); - assertThat(api.grants().apiToken, is("new token")); - assertThat(api.guardian().apiToken, is("new token")); - assertThat(api.jobs().apiToken, is("new token")); - assertThat(api.logEvents().apiToken, is("new token")); - assertThat(api.resourceServers().apiToken, is("new token")); - assertThat(api.rules().apiToken, is("new token")); - assertThat(api.stats().apiToken, is("new token")); - assertThat(api.tenants().apiToken, is("new token")); - assertThat(api.tickets().apiToken, is("new token")); - assertThat(api.userBlocks().apiToken, is("new token")); - assertThat(api.users().apiToken, is("new token")); - } - - @Test - public void shouldUseDefaultTimeoutIfNotSpecified() { + @SuppressWarnings("deprecation") + public void shouldCreateWithDomainAndToken() { ManagementAPI api = new ManagementAPI(DOMAIN, API_TOKEN); - assertThat(api.getClient().connectTimeoutMillis(), is(10 * 1000)); - assertThat(api.getClient().readTimeoutMillis(), is(10 * 1000)); - } - - @Test - public void shouldUseZeroIfNegativeTimeoutConfigured() { - HttpOptions options = new HttpOptions(); - options.setConnectTimeout(-1); - options.setReadTimeout(-1); - ManagementAPI api = new ManagementAPI(DOMAIN, API_TOKEN, options); - assertThat(api.getClient().connectTimeoutMillis(), is(0)); - assertThat(api.getClient().readTimeoutMillis(), is(0)); - + assertThat(api, is(notNullValue())); } @Test - public void shouldSetTimeoutsIfConfigured() { - HttpOptions options = new HttpOptions(); - options.setConnectTimeout(20); - options.setReadTimeout(30); - ManagementAPI api = new ManagementAPI(DOMAIN, API_TOKEN, options); - assertThat(api.getClient().connectTimeoutMillis(), is(20 * 1000)); - assertThat(api.getClient().readTimeoutMillis(), is(30 * 1000)); - } - - @Test - public void shouldNotUseProxyByDefault() throws Exception { - ManagementAPI api = new ManagementAPI(DOMAIN, API_TOKEN); - assertThat(api.getClient().proxy(), is(nullValue())); - Authenticator authenticator = api.getClient().proxyAuthenticator(); - assertThat(authenticator, is(notNullValue())); - - Route route = Mockito.mock(Route.class); - okhttp3.Request nonAuthenticatedRequest = new okhttp3.Request.Builder() - .url("https://test.com/app") - .addHeader("some-header", "some-value") - .build(); - okhttp3.Response nonAuthenticatedResponse = new okhttp3.Response.Builder() - .protocol(Protocol.HTTP_2) - .code(200) - .message("OK") - .request(nonAuthenticatedRequest) - .build(); - - okhttp3.Request processedRequest = authenticator.authenticate(route, nonAuthenticatedResponse); - assertThat(processedRequest, is(nullValue())); - } - - @Test - public void shouldUseProxy() throws Exception { - Proxy proxy = Mockito.mock(Proxy.class); - ProxyOptions proxyOptions = new ProxyOptions(proxy); - HttpOptions httpOptions = new HttpOptions(); - httpOptions.setProxyOptions(proxyOptions); - - ManagementAPI api = new ManagementAPI(DOMAIN, API_TOKEN, httpOptions); - assertThat(api.getClient().proxy(), is(proxy)); - Authenticator authenticator = api.getClient().proxyAuthenticator(); - assertThat(authenticator, is(notNullValue())); - - Route route = Mockito.mock(Route.class); - okhttp3.Request nonAuthenticatedRequest = new okhttp3.Request.Builder() - .url("https://test.com/app") - .addHeader("some-header", "some-value") - .build(); - okhttp3.Response nonAuthenticatedResponse = new okhttp3.Response.Builder() - .protocol(Protocol.HTTP_2) - .code(200) - .message("OK") - .request(nonAuthenticatedRequest) - .build(); - - okhttp3.Request processedRequest = authenticator.authenticate(route, nonAuthenticatedResponse); - - assertThat(processedRequest, is(nullValue())); - } - - @Test - public void shouldUseProxyWithAuthentication() throws Exception { - Proxy proxy = Mockito.mock(Proxy.class); - ProxyOptions proxyOptions = new ProxyOptions(proxy); - proxyOptions.setBasicAuthentication("johndoe", "psswd".toCharArray()); - assertThat(proxyOptions.getBasicAuthentication(), is("Basic am9obmRvZTpwc3N3ZA==")); - HttpOptions httpOptions = new HttpOptions(); - httpOptions.setProxyOptions(proxyOptions); - - ManagementAPI api = new ManagementAPI(DOMAIN, API_TOKEN, httpOptions); - assertThat(api.getClient().proxy(), is(proxy)); - Authenticator authenticator = api.getClient().proxyAuthenticator(); - assertThat(authenticator, is(notNullValue())); - - Route route = Mockito.mock(Route.class); - okhttp3.Request nonAuthenticatedRequest = new okhttp3.Request.Builder() - .url("https://test.com/app") - .addHeader("some-header", "some-value") - .build(); - okhttp3.Response nonAuthenticatedResponse = new okhttp3.Response.Builder() - .protocol(Protocol.HTTP_2) - .code(200) - .message("OK") - .request(nonAuthenticatedRequest) - .build(); - - okhttp3.Request processedRequest = authenticator.authenticate(route, nonAuthenticatedResponse); - - assertThat(processedRequest, is(notNullValue())); - assertThat(processedRequest.url(), is(HttpUrl.parse("https://test.com/app"))); - assertThat(processedRequest.header("Proxy-Authorization"), is(proxyOptions.getBasicAuthentication())); - assertThat(processedRequest.header("some-header"), is("some-value")); - } - - @Test - public void proxyShouldNotProcessAlreadyAuthenticatedRequest() throws Exception { - Proxy proxy = Mockito.mock(Proxy.class); - ProxyOptions proxyOptions = new ProxyOptions(proxy); - proxyOptions.setBasicAuthentication("johndoe", "psswd".toCharArray()); - assertThat(proxyOptions.getBasicAuthentication(), is("Basic am9obmRvZTpwc3N3ZA==")); - HttpOptions httpOptions = new HttpOptions(); - httpOptions.setProxyOptions(proxyOptions); - - ManagementAPI api = new ManagementAPI(DOMAIN, API_TOKEN, httpOptions); - assertThat(api.getClient().proxy(), is(proxy)); - Authenticator authenticator = api.getClient().proxyAuthenticator(); - assertThat(authenticator, is(notNullValue())); - - Route route = Mockito.mock(Route.class); - okhttp3.Request alreadyAuthenticatedRequest = new okhttp3.Request.Builder() - .url("https://test.com/app") - .addHeader("some-header", "some-value") - .header("Proxy-Authorization", "pre-existing-value") - .build(); - okhttp3.Response alreadyAuthenticatedResponse = new okhttp3.Response.Builder() - .protocol(Protocol.HTTP_2) - .code(200) - .message("OK") - .request(alreadyAuthenticatedRequest) - .build(); - - okhttp3.Request processedRequest = authenticator.authenticate(route, alreadyAuthenticatedResponse); - assertThat(processedRequest, is(nullValue())); - } - - @Test - public void shouldAddAndEnableTelemetryInterceptor() { - ManagementAPI api = new ManagementAPI(DOMAIN, API_TOKEN); - assertThat(api.getClient().interceptors(), hasItem(isA(TelemetryInterceptor.class))); - - for (Interceptor i : api.getClient().interceptors()) { - if (i instanceof TelemetryInterceptor) { - TelemetryInterceptor telemetry = (TelemetryInterceptor) i; - assertThat(telemetry.isEnabled(), is(true)); + public void shouldCreateWithHttpClientWithApiToken() { + Auth0HttpClient httpClient = new Auth0HttpClient() { + @Override + public Auth0HttpResponse sendRequest(Auth0HttpRequest request) { + return null; } - } - } - @Test - public void shouldUseCustomTelemetry() { - ManagementAPI api = new ManagementAPI(DOMAIN, API_TOKEN); - assertThat(api.getClient().interceptors(), hasItem(isA(TelemetryInterceptor.class))); - - Telemetry currentTelemetry = null; - for (Interceptor i : api.getClient().interceptors()) { - if (i instanceof TelemetryInterceptor) { - TelemetryInterceptor interceptor = (TelemetryInterceptor) i; - currentTelemetry = interceptor.getTelemetry(); + @Override + public CompletableFuture sendRequestAsync(Auth0HttpRequest request) { + return null; } - } - assertThat(currentTelemetry, is(notNullValue())); + }; - Telemetry newTelemetry = Mockito.mock(Telemetry.class); - api.setTelemetry(newTelemetry); + ManagementAPI api = ManagementAPI.newBuilder(DOMAIN, API_TOKEN) + .withHttpClient(httpClient).build(); - Telemetry updatedTelemetry = null; - for (Interceptor i : api.getClient().interceptors()) { - if (i instanceof TelemetryInterceptor) { - TelemetryInterceptor interceptor = (TelemetryInterceptor) i; - updatedTelemetry = interceptor.getTelemetry(); - } - } - assertThat(updatedTelemetry, is(newTelemetry)); + assertThat(api, is(notNullValue())); + assertThat(api.getHttpClient(), is(httpClient)); } @Test - public void shouldDisableTelemetryInterceptor() { - ManagementAPI api = new ManagementAPI(DOMAIN, API_TOKEN); - assertThat(api.getClient().interceptors(), hasItem(isA(TelemetryInterceptor.class))); - api.doNotSendTelemetry(); - - for (Interceptor i : api.getClient().interceptors()) { - if (i instanceof TelemetryInterceptor) { - TelemetryInterceptor telemetry = (TelemetryInterceptor) i; - assertThat(telemetry.isEnabled(), is(false)); + public void shouldCreateWithHttpClientWithTokenProvider() { + Auth0HttpClient httpClient = new Auth0HttpClient() { + @Override + public Auth0HttpResponse sendRequest(Auth0HttpRequest request) { + return null; } - } - } - @Test - public void shouldAddAndDisableLoggingInterceptor() { - ManagementAPI api = new ManagementAPI(DOMAIN, API_TOKEN); - assertThat(api.getClient().interceptors(), hasItem(isA(HttpLoggingInterceptor.class))); - - for (Interceptor i : api.getClient().interceptors()) { - if (i instanceof HttpLoggingInterceptor) { - HttpLoggingInterceptor logging = (HttpLoggingInterceptor) i; - assertThat(logging.getLevel(), is(Level.NONE)); + @Override + public CompletableFuture sendRequestAsync(Auth0HttpRequest request) { + return null; } - } - } + }; - @Test - @SuppressWarnings("deprecation") - public void shouldEnableLoggingInterceptor() { - ManagementAPI api = new ManagementAPI(DOMAIN, API_TOKEN); - assertThat(api.getClient().interceptors(), hasItem(isA(HttpLoggingInterceptor.class))); - api.setLoggingEnabled(true); - - for (Interceptor i : api.getClient().interceptors()) { - if (i instanceof HttpLoggingInterceptor) { - HttpLoggingInterceptor logging = (HttpLoggingInterceptor) i; - assertThat(logging.getLevel(), is(Level.BODY)); - } - } - } - - @Test - @SuppressWarnings("deprecation") - public void shouldDisableLoggingInterceptor() { - ManagementAPI api = new ManagementAPI(DOMAIN, API_TOKEN); - assertThat(api.getClient().interceptors(), hasItem(isA(HttpLoggingInterceptor.class))); - api.setLoggingEnabled(false); - - for (Interceptor i : api.getClient().interceptors()) { - if (i instanceof HttpLoggingInterceptor) { - HttpLoggingInterceptor logging = (HttpLoggingInterceptor) i; - assertThat(logging.getLevel(), is(Level.NONE)); - } - } - } - - @Test - public void shouldConfigureNoneLoggingFromOptions() { - LoggingOptions loggingOptions = new LoggingOptions(LoggingOptions.LogLevel.NONE); - HttpOptions options = new HttpOptions(); - options.setLoggingOptions(loggingOptions); - - ManagementAPI api = new ManagementAPI(DOMAIN, API_TOKEN, options); - assertThat(api.getClient().interceptors(), hasItem(isA(HttpLoggingInterceptor.class))); - - for (Interceptor i : api.getClient().interceptors()) { - if (i instanceof HttpLoggingInterceptor) { - HttpLoggingInterceptor logging = (HttpLoggingInterceptor) i; - assertThat(logging.getLevel(), is(Level.NONE)); - } - } - } - - @Test - public void shouldConfigureBasicLoggingFromOptions() { - LoggingOptions loggingOptions = new LoggingOptions(LoggingOptions.LogLevel.BASIC); - HttpOptions options = new HttpOptions(); - options.setLoggingOptions(loggingOptions); - - ManagementAPI api = new ManagementAPI(DOMAIN, API_TOKEN, options); - assertThat(api.getClient().interceptors(), hasItem(isA(HttpLoggingInterceptor.class))); - - for (Interceptor i : api.getClient().interceptors()) { - if (i instanceof HttpLoggingInterceptor) { - HttpLoggingInterceptor logging = (HttpLoggingInterceptor) i; - assertThat(logging.getLevel(), is(Level.BASIC)); - } - } + ManagementAPI api = ManagementAPI.newBuilder( + DOMAIN, + SimpleTokenProvider.create(API_TOKEN) + ) + .withHttpClient(httpClient) + .build(); + assertThat(api, is(notNullValue())); + assertThat(api.getHttpClient(), is(httpClient)); } @Test - public void shouldConfigureHeaderLoggingFromOptions() { - LoggingOptions loggingOptions = new LoggingOptions(LoggingOptions.LogLevel.HEADERS); - Set headersToRedact = new HashSet<>(); - headersToRedact.add("Authorization"); - headersToRedact.add("Cookie"); - loggingOptions.setHeadersToRedact(headersToRedact); - HttpOptions options = new HttpOptions(); - options.setLoggingOptions(loggingOptions); - - ManagementAPI api = new ManagementAPI(DOMAIN, API_TOKEN, options); - assertThat(api.getClient().interceptors(), hasItem(isA(HttpLoggingInterceptor.class))); + public void shouldAcceptDomainWithHttpScheme() { + ManagementAPI api = ManagementAPI.newBuilder("http://me.something.com", API_TOKEN).build(); - for (Interceptor i : api.getClient().interceptors()) { - if (i instanceof HttpLoggingInterceptor) { - HttpLoggingInterceptor logging = (HttpLoggingInterceptor) i; - assertThat(logging.getLevel(), is(Level.HEADERS)); - } - } + assertThat(api.getBaseUrl(), is(notNullValue())); + assertThat(api.getBaseUrl().toString(), isUrl("http", "me.something.com")); } @Test - public void shouldConfigureBodyLoggingFromOptions() { - LoggingOptions loggingOptions = new LoggingOptions(LoggingOptions.LogLevel.BODY); - Set headersToRedact = new HashSet<>(); - headersToRedact.add("Authorization"); - headersToRedact.add("Cookie"); - loggingOptions.setHeadersToRedact(headersToRedact); - HttpOptions options = new HttpOptions(); - options.setLoggingOptions(loggingOptions); - - ManagementAPI api = new ManagementAPI(DOMAIN, API_TOKEN, options); - assertThat(api.getClient().interceptors(), hasItem(isA(HttpLoggingInterceptor.class))); - - for (Interceptor i : api.getClient().interceptors()) { - if (i instanceof HttpLoggingInterceptor) { - HttpLoggingInterceptor logging = (HttpLoggingInterceptor) i; - assertThat(logging.getLevel(), is(Level.BODY)); - } - } + public void shouldThrowWhenDomainIsInvalid() { + verifyThrows(IllegalArgumentException.class, + () -> ManagementAPI.newBuilder("", API_TOKEN).build(), + "The domain had an invalid format and couldn't be parsed as an URL."); } @Test - public void shouldUseDefaultMaxRetriesIfNotConfigured() { - ManagementAPI api = new ManagementAPI(DOMAIN, API_TOKEN); - assertThat(api.getClient().interceptors(), hasItem(isA(RateLimitInterceptor.class))); - - for (Interceptor i : api.getClient().interceptors()) { - if (i instanceof RateLimitInterceptor) { - RateLimitInterceptor rateLimitInterceptor = (RateLimitInterceptor) i; - assertThat(rateLimitInterceptor.getMaxRetries(), is(3)); - } - } + public void shouldThrowWhenDomainIsNull() { + verifyThrows(IllegalArgumentException.class, + () -> ManagementAPI.newBuilder(null, API_TOKEN).build(), + "'domain' cannot be null!"); } @Test - public void shouldUseCustomMaxRetriesIfConfigured() { - HttpOptions options = new HttpOptions(); - options.setManagementAPIMaxRetries(5); - ManagementAPI api = new ManagementAPI(DOMAIN, API_TOKEN, options); - assertThat(api.getClient().interceptors(), hasItem(isA(RateLimitInterceptor.class))); - - for (Interceptor i : api.getClient().interceptors()) { - if (i instanceof RateLimitInterceptor) { - RateLimitInterceptor rateLimitInterceptor = (RateLimitInterceptor) i; - assertThat(rateLimitInterceptor.getMaxRetries(), is(5)); - } - } + public void shouldThrowWhenApiTokenIsNull() { + verifyThrows(IllegalArgumentException.class, + () -> ManagementAPI.newBuilder(DOMAIN, (String) null).build(), + "'api token' cannot be null!"); } @Test - public void shouldThrowOnNegativeMaxRetriesConfiguration() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("Retries must be between zero and ten."); - - HttpOptions options = new HttpOptions(); - options.setManagementAPIMaxRetries(-1); + public void shouldThrowWhenTokenProviderIsNull() { + verifyThrows(IllegalArgumentException.class, + () -> ManagementAPI.newBuilder(DOMAIN, (TokenProvider) null).build(), + "'token provider' cannot be null!"); } @Test - public void shouldThrowOnTooManyMaxRetriesConfiguration() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("Retries must be between zero and ten."); - - HttpOptions options = new HttpOptions(); - options.setManagementAPIMaxRetries(11); - } + public void shouldThrowOnUpdateWhenApiTokenIsNull() { + ManagementAPI api = ManagementAPI.newBuilder(DOMAIN, API_TOKEN).build(); - @Test - public void shouldUseDefaultMaxRequests() { - ManagementAPI api = new ManagementAPI(DOMAIN, API_TOKEN); - assertThat(api.getClient().dispatcher().getMaxRequests(), is(64)); + verifyThrows(IllegalArgumentException.class, + () -> api.setApiToken(null), + "'api token' cannot be null!"); } @Test - public void shouldUseConfiguredMaxRequests() { - HttpOptions options = new HttpOptions(); - options.setMaxRequests(10); - ManagementAPI api = new ManagementAPI(DOMAIN, API_TOKEN, options); - assertThat(api.getClient().dispatcher().getMaxRequests(), is(10)); - } + public void shouldUpdateApiToken() throws Auth0Exception { + //Initialize with a token + ManagementAPI api = ManagementAPI.newBuilder(DOMAIN, "first token").build(); + + assertThat(api.blacklists().tokenProvider.getToken(), is("first token")); + assertThat(api.clientGrants().tokenProvider.getToken(), is("first token")); + assertThat(api.clients().tokenProvider.getToken(), is("first token")); + assertThat(api.connections().tokenProvider.getToken(), is("first token")); + assertThat(api.deviceCredentials().tokenProvider.getToken(), is("first token")); + assertThat(api.emailProvider().tokenProvider.getToken(), is("first token")); + assertThat(api.emailTemplates().tokenProvider.getToken(), is("first token")); + assertThat(api.grants().tokenProvider.getToken(), is("first token")); + assertThat(api.guardian().tokenProvider.getToken(), is("first token")); + assertThat(api.jobs().tokenProvider.getToken(), is("first token")); + assertThat(api.logEvents().tokenProvider.getToken(), is("first token")); + assertThat(api.resourceServers().tokenProvider.getToken(), is("first token")); + assertThat(api.rules().tokenProvider.getToken(), is("first token")); + assertThat(api.stats().tokenProvider.getToken(), is("first token")); + assertThat(api.tenants().tokenProvider.getToken(), is("first token")); + assertThat(api.tickets().tokenProvider.getToken(), is("first token")); + assertThat(api.userBlocks().tokenProvider.getToken(), is("first token")); + assertThat(api.users().tokenProvider.getToken(), is("first token")); - @Test - public void shouldThrowOnInValidMaxRequestsConfiguration() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("maxRequests must be one or greater."); + //Update the token + api.setApiToken("new token"); - HttpOptions options = new HttpOptions(); - options.setMaxRequests(0); + assertThat(api.blacklists().tokenProvider.getToken(), is("new token")); + assertThat(api.clientGrants().tokenProvider.getToken(), is("new token")); + assertThat(api.clients().tokenProvider.getToken(), is("new token")); + assertThat(api.connections().tokenProvider.getToken(), is("new token")); + assertThat(api.deviceCredentials().tokenProvider.getToken(), is("new token")); + assertThat(api.emailProvider().tokenProvider.getToken(), is("new token")); + assertThat(api.emailTemplates().tokenProvider.getToken(), is("new token")); + assertThat(api.grants().tokenProvider.getToken(), is("new token")); + assertThat(api.guardian().tokenProvider.getToken(), is("new token")); + assertThat(api.jobs().tokenProvider.getToken(), is("new token")); + assertThat(api.logEvents().tokenProvider.getToken(), is("new token")); + assertThat(api.resourceServers().tokenProvider.getToken(), is("new token")); + assertThat(api.rules().tokenProvider.getToken(), is("new token")); + assertThat(api.stats().tokenProvider.getToken(), is("new token")); + assertThat(api.tenants().tokenProvider.getToken(), is("new token")); + assertThat(api.tickets().tokenProvider.getToken(), is("new token")); + assertThat(api.userBlocks().tokenProvider.getToken(), is("new token")); + assertThat(api.users().tokenProvider.getToken(), is("new token")); } @Test - public void shouldUseDefaultMaxRequestsPerHost() { - ManagementAPI api = new ManagementAPI(DOMAIN, API_TOKEN); - assertThat(api.getClient().dispatcher().getMaxRequestsPerHost(), is(5)); + @SuppressWarnings("deprecation") + public void acceptsHttpOptions() { + com.auth0.client.HttpOptions httpOptions = new com.auth0.client.HttpOptions(); + httpOptions.setConnectTimeout(15); + ManagementAPI api = new ManagementAPI(DOMAIN, "CLIENT_ID", httpOptions); + assertThat(api, is(notNullValue())); } @Test - public void shouldUseConfiguredMaxRequestsPerHost() { - HttpOptions options = new HttpOptions(); - options.setMaxRequestsPerHost(10); - ManagementAPI api = new ManagementAPI(DOMAIN, API_TOKEN, options); - assertThat(api.getClient().dispatcher().getMaxRequestsPerHost(), is(10)); + @SuppressWarnings("deprecation") + public void httpOptionsShouldThrowWhenNull() { + verifyThrows(IllegalArgumentException.class, () -> new ManagementAPI(DOMAIN, API_TOKEN, null)); } @Test + @SuppressWarnings("deprecation") public void shouldThrowOnInValidMaxRequestsPerHostConfiguration() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("maxRequestsPerHost must be one or greater."); + com.auth0.client.HttpOptions options = new com.auth0.client.HttpOptions(); - HttpOptions options = new HttpOptions(); - options.setMaxRequestsPerHost(0); + verifyThrows(IllegalArgumentException.class, + () -> options.setMaxRequestsPerHost(0), + "maxRequestsPerHost must be one or greater."); } //Entities diff --git a/src/test/java/com/auth0/client/mgmt/NetworkAclsEntityTest.java b/src/test/java/com/auth0/client/mgmt/NetworkAclsEntityTest.java new file mode 100644 index 000000000..49e31f78c --- /dev/null +++ b/src/test/java/com/auth0/client/mgmt/NetworkAclsEntityTest.java @@ -0,0 +1,235 @@ +package com.auth0.client.mgmt; + +import com.auth0.client.MockServer; +import com.auth0.client.mgmt.filter.NetworkAclsFilter; +import com.auth0.json.mgmt.networkacls.*; +import com.auth0.net.Request; +import com.auth0.net.client.HttpMethod; +import okhttp3.mockwebserver.RecordedRequest; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import static com.auth0.AssertsUtil.verifyThrows; +import static com.auth0.client.MockServer.*; +import static com.auth0.client.RecordedRequestMatcher.*; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; + +public class NetworkAclsEntityTest extends BaseMgmtEntityTest { + + // Network ACLs entity + + @Test + public void shouldListNetworkAclsWithoutFilter() throws Exception { + Request request = api.networkAcls().list(null); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MockServer.MGMT_NETWORK_ACLS_LIST, 200); + NetworkAclsPage response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/network-acls")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + assertThat(response, is(notNullValue())); + assertThat(response.getItems(), hasSize(2)); + } + + @Test + public void shouldListNetworkAclsWithFilter() throws Exception { + NetworkAclsFilter filter = new NetworkAclsFilter() + .withPage(0, 10) + .withTotals(true); + + Request request = api.networkAcls().list(filter); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MockServer.MGMT_NETWORK_ACLS_LIST, 200); + NetworkAclsPage response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/network-acls")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + assertThat(recordedRequest, hasQueryParameter("page", "0")); + assertThat(recordedRequest, hasQueryParameter("per_page", "10")); + assertThat(recordedRequest, hasQueryParameter("include_totals", "true")); + + assertThat(response, is(notNullValue())); + assertThat(response.getItems(), hasSize(2)); + } + + @Test + public void shouldThrowOnCreateNetworkAclWithNullNetworkAcls() { + verifyThrows(IllegalArgumentException.class, + () -> api.networkAcls().create(null), + "'network acls' cannot be null!"); + } + + @Test + public void shouldCreateNetworkAcl() throws Exception { + NetworkAcls networkAclsToCreate = new NetworkAcls(); + networkAclsToCreate.setDescription("Log America and Canada all the time."); + networkAclsToCreate.setActive(true); + networkAclsToCreate.setPriority(1); + Rule rule = new Rule(); + Action action = new Action(); + action.setLog(true); + rule.setAction(action); + + rule.setScope("authentication"); + + Match match = new Match(); + List geoCountryCodes = new ArrayList<>(); + geoCountryCodes.add("US"); + geoCountryCodes.add("CA"); + + match.setGeoCountryCodes(geoCountryCodes); + rule.setMatch(match); + networkAclsToCreate.setRule(rule); + + + Request request = api.networkAcls().create(networkAclsToCreate); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MockServer.MGMT_NETWORK_ACLS, 201); + NetworkAcls response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/network-acls")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + Map body = bodyFromRequest(recordedRequest); + assertThat(body, aMapWithSize(4)); + assertThat(body, hasEntry("description", "Log America and Canada all the time.")); + assertThat(body, hasEntry("active", true)); + assertThat(body, hasEntry("priority", 1)); + assertThat(body, hasEntry(is("rule"), is(notNullValue()))); + + assertThat(response, is(notNullValue())); + } + + @Test + public void shouldThrowOnGetNetworkAclWithNullId() { + verifyThrows(IllegalArgumentException.class, + () -> api.networkAcls().get(null), + "'id' cannot be null!"); + } + + @Test + public void shouldGetNetworkAcl() throws Exception { + Request request = api.networkAcls().get("acl_1"); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MockServer.MGMT_NETWORK_ACLS, 200); + NetworkAcls response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/network-acls/acl_1")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + assertThat(response, is(notNullValue())); + assertThat(response.getId(), is("acl_1")); + assertThat(response.getDescription(), is("Log America and Canada all the time.")); + } + + @Test + public void shouldThrowOnDeleteNetworkAclWithNullId() { + verifyThrows(IllegalArgumentException.class, + () -> api.networkAcls().delete(null), + "'id' cannot be null!"); + } + + @Test + public void shouldDeleteNetworkAcl() throws Exception { + Request request = api.networkAcls().delete("acl_1"); + assertThat(request, is(notNullValue())); + + server.emptyResponse(204); + request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/network-acls/acl_1")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + } + + @Test + public void shouldThrowOnUpdateNetworkAclWithNullId() { + verifyThrows(IllegalArgumentException.class, + () -> api.networkAcls().update(null, new NetworkAcls()), + "'id' cannot be null!"); + } + + @Test + public void shouldThrowOnUpdateNetworkAclWithNullNetworkAcls() { + verifyThrows(IllegalArgumentException.class, + () -> api.networkAcls().update("acl_1", null), + "'network acls' cannot be null!"); + } + + @Test + public void shouldUpdateNetworkAcl() throws Exception { + NetworkAcls networkAclsToUpdate = new NetworkAcls(); + networkAclsToUpdate.setDescription("Log America and Canada all the time."); + networkAclsToUpdate.setActive(false); + networkAclsToUpdate.setPriority(5); + + Request request = api.networkAcls().update("acl_1", networkAclsToUpdate); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MockServer.MGMT_NETWORK_ACLS, 200); + NetworkAcls response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PUT, "/api/v2/network-acls/acl_1")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + Map body = bodyFromRequest(recordedRequest); + assertThat(body, aMapWithSize(3)); + assertThat(body, hasEntry("description", "Log America and Canada all the time.")); + assertThat(body, hasEntry("active", false)); + assertThat(body, hasEntry("priority", 5)); + + assertThat(response, is(notNullValue())); + } + + @Test + public void shouldThrowOnPatchNetworkAclWithNullId() { + verifyThrows(IllegalArgumentException.class, + () -> api.networkAcls().patch(null, new NetworkAcls()), + "'id' cannot be null!"); + } + + @Test + public void shouldPatchNetworkAcl() throws Exception { + NetworkAcls networkAclsToPatch = new NetworkAcls(); + networkAclsToPatch.setActive(true); + networkAclsToPatch.setPriority(3); + + Request request = api.networkAcls().patch("acl_1", networkAclsToPatch); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MockServer.MGMT_NETWORK_ACLS, 200); + NetworkAcls response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PATCH, "/api/v2/network-acls/acl_1")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + Map body = bodyFromRequest(recordedRequest); + assertThat(body, aMapWithSize(2)); + assertThat(body, hasEntry("active", true)); + assertThat(body, hasEntry("priority", 3)); + + assertThat(response, is(notNullValue())); + } +} diff --git a/src/test/java/com/auth0/client/mgmt/OrganizationEntityTest.java b/src/test/java/com/auth0/client/mgmt/OrganizationEntityTest.java index bab39853e..2928ed95b 100644 --- a/src/test/java/com/auth0/client/mgmt/OrganizationEntityTest.java +++ b/src/test/java/com/auth0/client/mgmt/OrganizationEntityTest.java @@ -1,21 +1,30 @@ package com.auth0.client.mgmt; import com.auth0.client.MockServer; -import com.auth0.client.mgmt.filter.FieldsFilter; -import com.auth0.client.mgmt.filter.InvitationsFilter; -import com.auth0.client.mgmt.filter.PageFilter; -import com.auth0.json.mgmt.RolesPage; +import com.auth0.client.mgmt.filter.*; +import com.auth0.exception.Auth0Exception; +import com.auth0.json.mgmt.client.Client; +import com.auth0.json.mgmt.client.ClientDefaultOrganization; +import com.auth0.json.mgmt.client.ClientsPage; +import com.auth0.json.mgmt.clientgrants.ClientGrant; +import com.auth0.json.mgmt.clientgrants.ClientGrantsPage; import com.auth0.json.mgmt.organizations.*; +import com.auth0.json.mgmt.resourceserver.ResourceServer; +import com.auth0.json.mgmt.roles.RolesPage; +import com.auth0.json.mgmt.tokenquota.ClientCredentials; +import com.auth0.json.mgmt.tokenquota.TokenQuota; import com.auth0.net.Request; +import com.auth0.net.client.HttpMethod; import okhttp3.mockwebserver.RecordedRequest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.*; +import static com.auth0.AssertsUtil.verifyThrows; import static com.auth0.client.MockServer.*; import static com.auth0.client.RecordedRequestMatcher.*; -import static org.hamcrest.Matchers.*; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; public class OrganizationEntityTest extends BaseMgmtEntityTest { @@ -27,10 +36,10 @@ public void shouldListOrgsWithoutFilter() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MockServer.ORGANIZATIONS_LIST, 200); - OrganizationsPage response = request.execute(); + OrganizationsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/organizations")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/organizations")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -45,10 +54,10 @@ public void shouldListOrgsWithPage() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MockServer.ORGANIZATIONS_PAGED_LIST, 200); - OrganizationsPage response = request.execute(); + OrganizationsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/organizations")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/organizations")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("page", "2")); @@ -65,10 +74,10 @@ public void shouldListOrgsWithCheckpointPagination() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(ORGANIZATIONS_CHECKPOINT_PAGED_LIST, 200); - OrganizationsPage response = request.execute(); + OrganizationsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/organizations")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/organizations")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("take", "10")); @@ -85,10 +94,10 @@ public void shouldListOrgsWithTotals() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MockServer.ORGANIZATIONS_PAGED_LIST, 200); - OrganizationsPage response = request.execute(); + OrganizationsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/organizations")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/organizations")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("include_totals", "true")); @@ -99,9 +108,9 @@ public void shouldListOrgsWithTotals() throws Exception { @Test public void shouldThrowOnGetOrgWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("organization ID"); - api.organizations().get(null); + verifyThrows(IllegalArgumentException.class, + () -> api.organizations().get(null), + "'organization ID' cannot be null!"); } @Test @@ -110,10 +119,10 @@ public void shouldGetOrganization() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MockServer.ORGANIZATION, 200); - Organization response = request.execute(); + Organization response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/organizations/org_123")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/organizations/org_123")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -122,9 +131,9 @@ public void shouldGetOrganization() throws Exception { @Test public void shouldThrowOnGetOrgWithNullName() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("organization name"); - api.organizations().getByName(null); + verifyThrows(IllegalArgumentException.class, + () -> api.organizations().getByName( null), + "'organization name' cannot be null!"); } @Test @@ -133,10 +142,10 @@ public void shouldGetOrganizationByName() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MockServer.ORGANIZATION, 200); - Organization response = request.execute(); + Organization response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/organizations/name/org-1")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/organizations/name/org-1")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -145,9 +154,9 @@ public void shouldGetOrganizationByName() throws Exception { @Test public void shouldThrowOnCreateOrgWithNullOrg() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("organization"); - api.organizations().create(null); + verifyThrows(IllegalArgumentException.class, + () -> api.organizations().create(null), + "'organization' cannot be null!"); } @Test @@ -174,40 +183,57 @@ public void shouldCreateOrganization() throws Exception { enabledConnections.add(enabledConnection); orgToCreate.setEnabledConnections(enabledConnections); + ClientCredentials clientCredentials = new ClientCredentials(); + clientCredentials.setPerDay(100); + clientCredentials.setPerHour(20); + clientCredentials.setEnforce(true); + + TokenQuota tokenQuota = new TokenQuota(clientCredentials); + orgToCreate.setTokenQuota(tokenQuota); + Request request = api.organizations().create(orgToCreate); assertThat(request, is(notNullValue())); server.jsonResponse(MockServer.ORGANIZATION, 200); - Organization response = request.execute(); + Organization response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/api/v2/organizations")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/organizations")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); Map body = bodyFromRequest(recordedRequest); - assertThat(body, aMapWithSize(5)); + assertThat(body, aMapWithSize(6)); assertThat(body, hasEntry("name", "test-org")); assertThat(body, hasEntry("display_name", "display name")); assertThat(body, hasEntry("metadata", metadata)); assertThat(body, hasEntry(is("enabled_connections"), is(notNullValue()))); assertThat(body, hasEntry(is("branding"), is(notNullValue()))); + assertThat(body, hasEntry(is("token_quota"), is(notNullValue()))); + Map tokenQuotaMap = (Map) body.get("token_quota"); + assertThat(tokenQuotaMap, is(notNullValue())); + Map clientCredentialsMap = (Map) tokenQuotaMap.get("client_credentials"); + assertThat(clientCredentialsMap, is(notNullValue())); + assertThat(clientCredentialsMap, hasEntry("per_day", 100)); + assertThat(clientCredentialsMap, hasEntry("per_hour", 20)); + assertThat(clientCredentialsMap, hasEntry("enforce", true)); + assertThat(response, is(notNullValue())); } @Test public void shouldThrowOnUpdateOrgWithNullOrgId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("organization ID"); - api.organizations().update(null, new Organization()); + verifyThrows(IllegalArgumentException.class, + () -> api.organizations().update(null, new Organization()), + "'organization ID' cannot be null!"); } @Test public void shouldThrowOnUpdateOrgWithNullOrg() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("organization"); - api.organizations().update("org_123", null); + verifyThrows(IllegalArgumentException.class, + () -> api.organizations().update("org_123", null), + "'organization' cannot be null!"); } @Test @@ -227,32 +253,50 @@ public void shouldUpdateOrganization() throws Exception { metadata.put("key1", "val1"); orgToUpdate.setMetadata(metadata); + ClientCredentials clientCredentials = new ClientCredentials(); + clientCredentials.setPerDay(100); + clientCredentials.setPerHour(20); + clientCredentials.setEnforce(true); + + TokenQuota tokenQuota = new TokenQuota(clientCredentials); + orgToUpdate.setTokenQuota(tokenQuota); + Request request = api.organizations().update("org_abc", orgToUpdate); assertThat(request, is(notNullValue())); server.jsonResponse(MockServer.ORGANIZATION, 200); - Organization response = request.execute(); + Organization response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("PATCH", "/api/v2/organizations/org_abc")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PATCH, "/api/v2/organizations/org_abc")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); Map body = bodyFromRequest(recordedRequest); - assertThat(body, aMapWithSize(4)); + assertThat(body, aMapWithSize(5)); assertThat(body, hasEntry("name", "test-org")); assertThat(body, hasEntry("display_name", "display name")); assertThat(body, hasEntry("metadata", metadata)); assertThat(body, hasEntry(is("branding"), is(notNullValue()))); + assertThat(body, hasEntry(is("token_quota"), is(notNullValue()))); + + Map tokenQuotaMap = (Map) body.get("token_quota"); + assertThat(tokenQuotaMap, is(notNullValue())); + Map clientCredentialsMap = (Map) tokenQuotaMap.get("client_credentials"); + assertThat(clientCredentialsMap, is(notNullValue())); + assertThat(clientCredentialsMap, hasEntry("per_day", 100)); + assertThat(clientCredentialsMap, hasEntry("per_hour", 20)); + assertThat(clientCredentialsMap, hasEntry("enforce", true)); + assertThat(response, is(notNullValue())); } @Test public void shouldThrowOnDeleteOrgWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("organization ID"); - api.organizations().delete(null); + verifyThrows(IllegalArgumentException.class, + () -> api.organizations().delete(null), + "'organization ID' cannot be null!"); } @Test @@ -261,10 +305,10 @@ public void shouldDeleteOrganization() throws Exception { assertThat(request, is(notNullValue())); server.emptyResponse(204); - request.execute(); + request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("DELETE", "/api/v2/organizations/org_abc")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/organizations/org_abc")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); } @@ -273,9 +317,9 @@ public void shouldDeleteOrganization() throws Exception { @Test public void shouldThrowOnGetMembersWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("organization ID"); - api.organizations().getMembers(null, null); + verifyThrows(IllegalArgumentException.class, + () -> api.organizations().getMembers(null, null), + "'organization ID' cannot be null!"); } @Test @@ -284,12 +328,33 @@ public void shouldListOrgMembersWithoutFilter() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MockServer.ORGANIZATION_MEMBERS_LIST, 200); - MembersPage response = request.execute(); + MembersPage response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/organizations/org_abc/members")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + assertThat(response, is(notNullValue())); + assertThat(response.getItems(), hasSize(3)); + } + + @Test + public void shouldListOrgMembersWithFieldsFilter() throws Exception { + FieldsFilter fieldsFilter = new FieldsFilter().withFields("name,email,user_id,roles", true); + + Request request = api.organizations().getMembers("org_abc", null, fieldsFilter); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MockServer.ORGANIZATION_MEMBERS_LIST, 200); + MembersPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/organizations/org_abc/members")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/organizations/org_abc/members")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + assertThat(recordedRequest, hasQueryParameter("fields", "name,email,user_id,roles")); + assertThat(recordedRequest, hasQueryParameter("include_fields", "true")); assertThat(response, is(notNullValue())); assertThat(response.getItems(), hasSize(3)); @@ -302,12 +367,36 @@ public void shouldListOrgMembersWithPage() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MockServer.ORGANIZATION_MEMBERS_LIST, 200); - MembersPage response = request.execute(); + MembersPage response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/organizations/org_abc/members")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + assertThat(recordedRequest, hasQueryParameter("page", "0")); + assertThat(recordedRequest, hasQueryParameter("per_page", "20")); + + assertThat(response, is(notNullValue())); + assertThat(response.getItems(), hasSize(3)); + } + + @Test + public void shouldListOrgMembersWithFieldsFilterAndPageFilter() throws Exception { + PageFilter pageFilter = new PageFilter().withPage(0, 20); + FieldsFilter fieldsFilter = new FieldsFilter().withFields("name,email,user_id,roles", true); + + Request request = api.organizations().getMembers("org_abc", pageFilter, fieldsFilter); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MockServer.ORGANIZATION_MEMBERS_LIST, 200); + MembersPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/organizations/org_abc/members")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/organizations/org_abc/members")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + assertThat(recordedRequest, hasQueryParameter("fields", "name,email,user_id,roles")); + assertThat(recordedRequest, hasQueryParameter("include_fields", "true")); assertThat(recordedRequest, hasQueryParameter("page", "0")); assertThat(recordedRequest, hasQueryParameter("per_page", "20")); @@ -322,10 +411,10 @@ public void shouldListOrgMembersWithTotals() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MockServer.ORGANIZATION_MEMBERS_PAGED_LIST, 200); - MembersPage response = request.execute(); + MembersPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/organizations/org_abc/members")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/organizations/org_abc/members")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("include_totals", "true")); @@ -341,10 +430,10 @@ public void shouldListOrgMembersWithCheckpointPageResponse() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(ORGANIZATION_MEMBERS_CHECKPOINT_PAGED_LIST, 200); - MembersPage response = request.execute(); + MembersPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/organizations/org_abc/members")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/organizations/org_abc/members")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("take", "3")); @@ -356,16 +445,16 @@ public void shouldListOrgMembersWithCheckpointPageResponse() throws Exception { @Test public void shouldThrowOnAddMembersWhenOrgIdNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("organization ID"); - api.organizations().addMembers(null, new Members(Collections.singletonList("user1"))); + verifyThrows(IllegalArgumentException.class, + () -> api.organizations().addMembers(null, new Members(Collections.singletonList("user1"))), + "'organization ID' cannot be null!"); } @Test public void shouldThrowOnAddMembersWhenMembersIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("members"); - api.organizations().addMembers("org_abc", null); + verifyThrows(IllegalArgumentException.class, + () -> api.organizations().addMembers("org_abc", null), + "'members' cannot be null!"); } @Test @@ -376,10 +465,10 @@ public void shouldAddMembersToOrganization() throws Exception { assertThat(request, is(notNullValue())); server.emptyResponse(204); - request.execute(); + request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/api/v2/organizations/org_abc/members")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/organizations/org_abc/members")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -390,16 +479,16 @@ public void shouldAddMembersToOrganization() throws Exception { @Test public void shouldThrowOnDeleteMembersWhenOrgIdNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("organization ID"); - api.organizations().deleteMembers(null, new Members(Collections.singletonList("user1"))); + verifyThrows(IllegalArgumentException.class, + () -> api.organizations().deleteMembers(null, new Members(Collections.singletonList("user1"))), + "'organization ID' cannot be null!"); } @Test public void shouldThrowOnDeleteMembersWhenMembersIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("members"); - api.organizations().deleteMembers("org_abc", null); + verifyThrows(IllegalArgumentException.class, + () -> api.organizations().deleteMembers("org_abc", null), + "'members' cannot be null!"); } @Test @@ -410,10 +499,10 @@ public void shouldDeleteMembersFromOrganization() throws Exception { assertThat(request, is(notNullValue())); server.emptyResponse(204); - request.execute(); + request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("DELETE", "/api/v2/organizations/org_abc/members")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/organizations/org_abc/members")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -426,9 +515,9 @@ public void shouldDeleteMembersFromOrganization() throws Exception { @Test public void shouldThrowOnGetConnectionsWhenOrgIdNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("organization ID"); - api.organizations().deleteMembers(null, null); + verifyThrows(IllegalArgumentException.class, + () -> api.organizations().deleteMembers(null, null), + "'organization ID' cannot be null!"); } @Test @@ -437,10 +526,10 @@ public void shouldListOrganizationConnectionsWithoutFilter() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MockServer.ORGANIZATION_CONNECTIONS_LIST, 200); - EnabledConnectionsPage response = request.execute(); + EnabledConnectionsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/organizations/org_abc/enabled_connections")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/organizations/org_abc/enabled_connections")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -455,10 +544,10 @@ public void shouldGetOrganizationConnectionsWithPage() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MockServer.ORGANIZATION_CONNECTIONS_LIST, 200); - EnabledConnectionsPage response = request.execute(); + EnabledConnectionsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/organizations/org_abc/enabled_connections")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/organizations/org_abc/enabled_connections")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("page", "2")); @@ -475,10 +564,10 @@ public void shouldGetOrganizationConnectionsWithTotals() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MockServer.ORGANIZATION_CONNECTIONS_PAGED_LIST, 200); - EnabledConnectionsPage response = request.execute(); + EnabledConnectionsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/organizations/org_abc/enabled_connections")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/organizations/org_abc/enabled_connections")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("include_totals", "true")); @@ -489,16 +578,16 @@ public void shouldGetOrganizationConnectionsWithTotals() throws Exception { @Test public void shouldThrowOnGetConnectionWhenOrgIdNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("organization ID"); - api.organizations().getConnection(null, "con_id"); + verifyThrows(IllegalArgumentException.class, + () -> api.organizations().getConnection(null, "con_id"), + "'organization ID' cannot be null!"); } @Test public void shouldThrowOnGetConnectionWhenConnectionIdNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("connection ID"); - api.organizations().getConnection("org_abc", null); + verifyThrows(IllegalArgumentException.class, + () -> api.organizations().getConnection("org_abc",null), + "'connection ID' cannot be null!"); } @Test @@ -507,10 +596,10 @@ public void shouldGetConnection() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(ORGANIZATION_CONNECTION, 200); - EnabledConnection response = request.execute(); + EnabledConnection response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/organizations/org_123/enabled_connections/con_abc")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/organizations/org_123/enabled_connections/con_abc")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -519,16 +608,16 @@ public void shouldGetConnection() throws Exception { @Test public void shouldThrowOnAddConnectionWhenOrgIdNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("organization ID"); - api.organizations().addConnection(null, new EnabledConnection()); + verifyThrows(IllegalArgumentException.class, + () -> api.organizations().addConnection(null, new EnabledConnection()), + "'organization ID' cannot be null!"); } @Test public void shouldThrowOnAddConnectionWhenConnectionIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("connection"); - api.organizations().addConnection("org_abc", null); + verifyThrows(IllegalArgumentException.class, + () -> api.organizations().addConnection("org_abc", null), + "'connection' cannot be null!"); } @Test @@ -536,36 +625,38 @@ public void shouldAddConnection() throws Exception { EnabledConnection connection = new EnabledConnection(); connection.setAssignMembershipOnLogin(false); connection.setConnectionId("con_123"); + connection.setShowAsButton(true); Request request = api.organizations().addConnection("org_abc", connection); assertThat(request, is(notNullValue())); server.jsonResponse(ORGANIZATION_CONNECTION, 201); - request.execute(); + request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/api/v2/organizations/org_abc/enabled_connections")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/organizations/org_abc/enabled_connections")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); Map body = bodyFromRequest(recordedRequest); - assertThat(body, aMapWithSize(2)); + assertThat(body, aMapWithSize(3)); assertThat(body, hasEntry("connection_id", "con_123")); assertThat(body, hasEntry("assign_membership_on_login", false)); + assertThat(body, hasEntry("show_as_button", true)); } @Test public void shouldThrowOnDeleteConnectionWhenOrgIdNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("organization ID"); - api.organizations().deleteConnection(null, "con_123"); + verifyThrows(IllegalArgumentException.class, + () -> api.organizations().deleteConnection(null, "con_123"), + "'organization ID' cannot be null!"); } @Test public void shouldThrowOnDeleteConnectionWhenConnectionIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("connection"); - api.organizations().deleteConnection("org_abc", null); + verifyThrows(IllegalArgumentException.class, + () -> api.organizations().deleteConnection("org_abc", null), + "'connection ID' cannot be null!"); } @Test @@ -574,70 +665,73 @@ public void shouldDeleteConnection() throws Exception { assertThat(request, is(notNullValue())); server.emptyResponse(204); - request.execute(); + request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("DELETE", "/api/v2/organizations/org_abc/enabled_connections/con_123")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/organizations/org_abc/enabled_connections/con_123")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); } @Test public void shouldThrowOnUpdateConnectionWhenOrgIdNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("organization ID"); - api.organizations().updateConnection(null, "con_123", new EnabledConnection()); + verifyThrows(IllegalArgumentException.class, + () -> api.organizations().updateConnection(null, "con_123", new EnabledConnection()), + "'organization ID' cannot be null!"); } @Test public void shouldThrowOnUpdateConnectionWhenUserIdIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("connection"); - api.organizations().updateConnection("org_abc", null, new EnabledConnection()); + verifyThrows(IllegalArgumentException.class, + () -> api.organizations().updateConnection("org_abc", null, new EnabledConnection()), + "'connection ID' cannot be null!"); } @Test public void shouldThrowOnUpdateConnectionWhenConnectionIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("connection"); - api.organizations().updateConnection("org_abc", "con_123", null); + verifyThrows(IllegalArgumentException.class, + () -> api.organizations().updateConnection("org_abc", "con_123", null), + "'connection' cannot be null!"); + } @Test public void shouldUpdateOrgConnection() throws Exception { EnabledConnection connection = new EnabledConnection(); connection.setAssignMembershipOnLogin(true); + connection.setShowAsButton(false); Request request = api.organizations().updateConnection("org_abc", "con_123", connection); assertThat(request, is(notNullValue())); server.jsonResponse(ORGANIZATION_CONNECTION, 201); - request.execute(); + request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("PATCH", "/api/v2/organizations/org_abc/enabled_connections/con_123")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PATCH, "/api/v2/organizations/org_abc/enabled_connections/con_123")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); Map body = bodyFromRequest(recordedRequest); - assertThat(body, aMapWithSize(1)); + assertThat(body, aMapWithSize(2)); assertThat(body, hasEntry("assign_membership_on_login", true)); + assertThat(body, hasEntry("show_as_button", false)); } // Organization roles @Test public void shouldThrowOnGetOrgRolesWhenOrgIdIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("organization ID"); - api.organizations().getRoles(null, "user_123",null); + verifyThrows(IllegalArgumentException.class, + () -> api.organizations().getRoles(null, "user_123", null), + "'organization ID' cannot be null!"); } @Test public void shouldThrowOnGetOrgRolesWhenUserIdIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("user ID"); - api.organizations().getRoles("org_abc", null, null); + verifyThrows(IllegalArgumentException.class, + () -> api.organizations().getRoles("org_abc", null, null), + "'user ID' cannot be null!"); } @Test @@ -646,10 +740,10 @@ public void shouldGetOrgRolesWithoutPaging() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(ORGANIZATION_MEMBER_ROLES_LIST, 200); - RolesPage response = request.execute(); + RolesPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/organizations/org_abc/members/user_123/roles")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/organizations/org_abc/members/user_123/roles")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -663,10 +757,10 @@ public void shouldGetOrgRolesWithPaging() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(ORGANIZATION_MEMBER_ROLES_LIST, 200); - RolesPage response = request.execute(); + RolesPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/organizations/org_abc/members/user_123/roles")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/organizations/org_abc/members/user_123/roles")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("page", "0")); @@ -682,10 +776,10 @@ public void shouldGetOrgRolesWithIncludeTotals() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(ORGANIZATION_MEMBER_ROLES_PAGED_LIST, 200); - RolesPage response = request.execute(); + RolesPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/organizations/org_abc/members/user_123/roles")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/organizations/org_abc/members/user_123/roles")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("include_totals", "true")); @@ -696,23 +790,23 @@ public void shouldGetOrgRolesWithIncludeTotals() throws Exception { @Test public void shouldThrowOnAddOrgRolesWhenOrgIdIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("organization ID"); - api.organizations().addRoles(null, "user_123", new Roles(Collections.singletonList("role_id"))); + verifyThrows(IllegalArgumentException.class, + () -> api.organizations().addRoles(null, "user_123", new Roles(Collections.singletonList("role_id"))), + "'organization ID' cannot be null!"); } @Test public void shouldThrowOnAddOrgRolesWhenUserIdIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("user ID"); - api.organizations().addRoles("org_abc", null, new Roles(Collections.singletonList("role_id"))); + verifyThrows(IllegalArgumentException.class, + () -> api.organizations().addRoles("org_abc", null, new Roles(Collections.singletonList("role_id"))), + "'user ID' cannot be null!"); } @Test public void shouldThrowOnAddOrgRolesWhenRolesIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("roles"); - api.organizations().addRoles("org_abc", "user_123", null); + verifyThrows(IllegalArgumentException.class, + () -> api.organizations().addRoles("org_abc", "user_123", null), + "'roles' cannot be null!"); } @Test @@ -722,10 +816,10 @@ public void shouldAddOrgRoles() throws Exception { assertThat(request, is(notNullValue())); server.emptyResponse(204); - request.execute(); + request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/api/v2/organizations/org_abc/members/user_123/roles")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/organizations/org_abc/members/user_123/roles")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -736,23 +830,24 @@ public void shouldAddOrgRoles() throws Exception { @Test public void shouldThrowOnDeleteOrgRolesWhenOrgIdIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("organization ID"); - api.organizations().deleteRoles(null, "user_123", new Roles(Collections.singletonList("role_id"))); + verifyThrows(IllegalArgumentException.class, + () -> api.organizations().deleteRoles(null, "user_123", new Roles(Collections.singletonList("role_id"))), + "'organization ID' cannot be null!"); } @Test public void shouldThrowDeleteOrgRolesWhenUserIdIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("user ID"); - api.organizations().deleteRoles("org_abc", null, new Roles(Collections.singletonList("role_id"))); + verifyThrows(IllegalArgumentException.class, + () -> api.organizations().deleteRoles("org_abc", null, new Roles(Collections.singletonList("role_id"))), + "'user ID' cannot be null!"); } @Test public void shouldThrowOnDeleteOrgRolesWhenRolesIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("roles"); - api.organizations().deleteRoles("org_abc", "user_123", null); + verifyThrows(IllegalArgumentException.class, + () -> api.organizations().deleteRoles("org_abc", "user_123", null), + "'roles' cannot be null!"); + } @Test @@ -762,10 +857,10 @@ public void shouldDeleteOrgRoles() throws Exception { assertThat(request, is(notNullValue())); server.emptyResponse(204); - request.execute(); + request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("DELETE", "/api/v2/organizations/org_abc/members/user_123/roles")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/organizations/org_abc/members/user_123/roles")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -778,16 +873,16 @@ public void shouldDeleteOrgRoles() throws Exception { @Test public void shouldThrowOnGetInvitationWithNullOrgId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("organization ID"); - api.organizations().getInvitation(null, "invitation_id", null); + verifyThrows(IllegalArgumentException.class, + () -> api.organizations().getInvitation(null, "invitation_id", null), + "'organization ID' cannot be null!"); } @Test public void shouldThrowOnGetInvitationWithNullInvitationId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("invitation ID"); - api.organizations().getInvitation("org_id", null, null); + verifyThrows(IllegalArgumentException.class, + () -> api.organizations().getInvitation("org_id", null, null), + "'invitation ID' cannot be null!"); } @Test @@ -796,10 +891,10 @@ public void shouldGetInvitationWithoutFilter() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(INVITATION, 200); - Invitation response = request.execute(); + Invitation response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/organizations/org_123/invitations/invitation_id")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/organizations/org_123/invitations/invitation_id")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -813,10 +908,10 @@ public void shouldGetInvitationWithFilter() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(INVITATION, 200); - Invitation response = request.execute(); + Invitation response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/organizations/org_123/invitations/invitation_id")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/organizations/org_123/invitations/invitation_id")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("fields", "id,invitation_url,invitee")); @@ -827,9 +922,9 @@ public void shouldGetInvitationWithFilter() throws Exception { @Test public void shouldThrowOnGetInvitationsWithNullOrgId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("organization ID"); - api.organizations().getInvitations(null, null); + verifyThrows(IllegalArgumentException.class, + () -> api.organizations().getInvitations(null, null), + "'organization ID' cannot be null!"); } @Test @@ -838,10 +933,10 @@ public void shouldGetInvitationsWithoutFilter() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(INVITATIONS_LIST, 200); - InvitationsPage response = request.execute(); + InvitationsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/organizations/org_123/invitations")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/organizations/org_123/invitations")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -858,10 +953,10 @@ public void shouldGetInvitationsWithFilter() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(INVITATIONS_LIST, 200); - InvitationsPage response = request.execute(); + InvitationsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/organizations/org_123/invitations")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/organizations/org_123/invitations")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("fields", "invitee,inviter,created_at")); @@ -879,10 +974,10 @@ public void shouldGetInvitationsWithPaging() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(INVITATIONS_LIST, 200); - InvitationsPage response = request.execute(); + InvitationsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/organizations/org_123/invitations")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/organizations/org_123/invitations")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("per_page", "20")); @@ -899,10 +994,10 @@ public void shouldGetInvitationsWithTotals() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(INVITATIONS_PAGED_LIST, 200); - InvitationsPage response = request.execute(); + InvitationsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/organizations/org_123/invitations")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/organizations/org_123/invitations")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("include_totals", "true")); @@ -912,16 +1007,16 @@ public void shouldGetInvitationsWithTotals() throws Exception { @Test public void shouldThrowOnCreateInvitationWithNullOrgId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("organization ID"); - api.organizations().createInvitation(null, null); + verifyThrows(IllegalArgumentException.class, + () -> api.organizations().createInvitation(null, null), + "'organization ID' cannot be null!"); } @Test public void shouldThrowOnCreateInvitationWithNullInvitation() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("invitation"); - api.organizations().createInvitation("org_abc", null); + verifyThrows(IllegalArgumentException.class, + () -> api.organizations().createInvitation("org_abc", null), + "'invitation' cannot be null!"); } @Test @@ -936,10 +1031,10 @@ public void shouldCreateInvitation() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(INVITATION, 201); - Invitation response = request.execute(); + Invitation response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/api/v2/organizations/org_123/invitations")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/organizations/org_123/invitations")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -956,16 +1051,16 @@ public void shouldCreateInvitation() throws Exception { @Test public void shouldThrowOnDeleteInvitationWithNullOrgId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("organization ID"); - api.organizations().deleteInvitation(null, "inv_123"); + verifyThrows(IllegalArgumentException.class, + () -> api.organizations().deleteInvitation(null, "inv_123"), + "'organization ID' cannot be null!"); } @Test public void shouldThrowOnDeleteInvitationWithNullInvitationId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("invitation ID"); - api.organizations().deleteInvitation("org_abc", null); + verifyThrows(IllegalArgumentException.class, + () -> api.organizations().deleteInvitation("org_abc", null), + "'invitation ID' cannot be null!"); } @Test @@ -974,11 +1069,253 @@ public void shouldDeleteInvitation() throws Exception { assertThat(request, is(notNullValue())); server.emptyResponse(204); - request.execute(); + request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/organizations/org_abc/invitations/inv_123")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + } + + @Test + public void shouldListClientGrantsWithoutFilter() throws Exception { + Request request = api.organizations().listClientGrants("orgId", null); + assertThat(request, is(notNullValue())); + + server.jsonResponse(ORGANIZATION_CLIENT_GRANTS, 200); + OrganizationClientGrantsPage response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/organizations/orgId/client-grants")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + assertThat(response, is(notNullValue())); + assertThat(response.getItems(), hasSize(2)); + } + + @Test + public void shouldListClientGrantsWithFilter() throws Exception { + OrganizationClientGrantsFilter filter = new OrganizationClientGrantsFilter(); + filter + .withClientId("clientId") + .withAudience("https://api-identifier/") + .withPage(1, 2) + .withTotals(true); + + Request request = api.organizations().listClientGrants("orgId", filter); + assertThat(request, is(notNullValue())); + + server.jsonResponse(ORGANIZATION_CLIENT_GRANTS_PAGED_LIST, 200); + OrganizationClientGrantsPage response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/organizations/orgId/client-grants")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + assertThat(recordedRequest, hasQueryParameter("page", "1")); + assertThat(recordedRequest, hasQueryParameter("per_page", "2")); + assertThat(recordedRequest, hasQueryParameter("include_totals", "true")); + assertThat(recordedRequest, hasQueryParameter("audience", "https://api-identifier/")); + assertThat(recordedRequest, hasQueryParameter("client_id", "clientId")); + + assertThat(response, is(notNullValue())); + assertThat(response.getItems(), hasSize(1)); + } + + @Test + public void shouldListClientGrantsWithGrantIds() throws Exception { + OrganizationClientGrantsFilter filter = new OrganizationClientGrantsFilter(); + filter + .withClientId("clientId") + .withAudience("https://api-identifier/") + .withGrantIds("cgr_123456789012,cgr_abcdefghijkl"); + + Request request = api.organizations().listClientGrants("orgId", filter); + assertThat(request, is(notNullValue())); + + server.jsonResponse(ORGANIZATION_CLIENT_GRANTS_PAGED_LIST, 200); + OrganizationClientGrantsPage response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/organizations/orgId/client-grants")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + assertThat(recordedRequest, hasQueryParameter("grant_ids", "cgr_123456789012,cgr_abcdefghijkl")); + assertThat(recordedRequest, hasQueryParameter("audience", "https://api-identifier/")); + assertThat(recordedRequest, hasQueryParameter("client_id", "clientId")); + + assertThat(response, is(notNullValue())); + assertThat(response.getItems(), hasSize(1)); + } + + @Test + public void shouldThrowOnGetClientGrantsWithNullOrgId() { + verifyThrows(IllegalArgumentException.class, + () -> api.organizations().listClientGrants(null, null), + "'organization ID' cannot be null!"); + } + + @Test + public void shouldCreateClientGrant() throws Exception { + CreateOrganizationClientGrantRequestBody requestBody = new CreateOrganizationClientGrantRequestBody("grant-id"); + + Request request = api.organizations().addClientGrant("org_123", requestBody); + + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_CLIENT_GRANT, 201); + OrganizationClientGrant response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/organizations/org_123/client-grants")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + Map body = bodyFromRequest(recordedRequest); + assertThat(body, aMapWithSize(1)); + assertThat(body, hasEntry("grant_id", "grant-id")); + + assertThat(response, is(notNullValue())); + } + + @Test + public void shouldThrowOnCreateClientGrantWithNullOrgId() { + verifyThrows(IllegalArgumentException.class, + () -> api.organizations().addClientGrant(null, new CreateOrganizationClientGrantRequestBody("id")), + "'organization ID' cannot be null!"); + } + + @Test + public void shouldThrowOnCreateClientGreatWithNullGrant() { + verifyThrows(IllegalArgumentException.class, + () -> api.organizations().addClientGrant("org_1213", null), + "'client grant' cannot be null!"); + } + + @Test + public void shouldDeleteClientGrant() throws Exception { + Request request = api.organizations().deleteClientGrant("org_abc", "grant_123"); + assertThat(request, is(notNullValue())); + + server.emptyResponse(204); + request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("DELETE", "/api/v2/organizations/org_abc/invitations/inv_123")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/organizations/org_abc/client-grants/grant_123")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); } + + @Test + public void shouldThrowOnDeleteClientGrantWithNullOrgId() { + verifyThrows(IllegalArgumentException.class, + () -> api.organizations().deleteClientGrant(null, "grant-id"), + "'organization ID' cannot be null!"); + } + + @Test + public void shouldThrowOnDeleteClientGreatWithNullGrant() { + verifyThrows(IllegalArgumentException.class, + () -> api.organizations().deleteClientGrant("org_1213", null), + "'client grant ID' cannot be null!"); + } + + @Test + public void testClientGrantsWithOrg() throws Auth0Exception { + + Organization organization = null; + ResourceServer resourceServer = null; + Client client = null; + ClientGrant clientGrant = null; + OrganizationClientGrant organizationClientGrant = null; + + try { + //Create organization + organization = givenAnOrganization(); + + //Create resource server + resourceServer = givenAResourceServer(); + + //Create client + client = createNewClient(organization.getId()); + + //Create client grants + clientGrant = createNewClientGrant(client, resourceServer); + + //Associates the grant with an organization. + organizationClientGrant = api.organizations().addClientGrant(organization.getId(), new CreateOrganizationClientGrantRequestBody(clientGrant.getId())).execute().getBody(); + + ClientFilter clientFilter = new ClientFilter(); + clientFilter.withQuery("client_grant.organization_id:" + organization.getId()); + + // List all clients associated with a ClientGrant given an organizationID as query param + ClientsPage clientsPage = api.clients().list(clientFilter).execute().getBody(); + + for (Client c : clientsPage.getItems()) { + assertThat(organization.getId(), is(c.getDefaultOrganization().getOrganizationId())); + } + + OrganizationClientGrantsFilter filter = new OrganizationClientGrantsFilter(); + filter.withGrantIds(clientGrant.getId()); + + // List all ClientGrants given a list of grant_ids as query param + OrganizationClientGrantsPage organizationClientGrantsPage = api.organizations().listClientGrants(organization.getId(), filter).execute().getBody(); + + assertThat(organizationClientGrantsPage.getItems().size(), is(1)); + assertThat(organizationClientGrantsPage.getItems().get(0).getClientId(), is(clientGrant.getClientId())); + + // Remove the associated ClientGrants + api.organizations().deleteClientGrant(organization.getId(), organizationClientGrant.getId()).execute(); + + // List all ClientGrants which should be an empty list since grant has been removed from the organization. + OrganizationClientGrantsPage organizationClientGrantsPage1 = api.organizations().listClientGrants(organization.getId(), filter).execute().getBody(); + assertThat(organizationClientGrantsPage1.getItems().size(), is(0)); + + // Delete the ClientGrant. + api.clientGrants().delete(clientGrant.getId()).execute(); + + // Retrieve the ClientGrant and ensure error is return since grant has been deleted. + ClientGrantsPage clientGrantsPage = api.clientGrants().list(new ClientGrantsFilter().withClientId(client.getClientId())).execute().getBody(); + assertThat(clientGrantsPage.getItems().size(), is(0)); + } + catch (Exception ex){ + ex.printStackTrace(); + } + } + + private ClientGrant createNewClientGrant(Client client, ResourceServer resourceServer) throws Auth0Exception { + ClientGrant clientGrant = new ClientGrant(); + clientGrant.setClientId(client.getClientId()); + clientGrant.setAudience(resourceServer.getIdentifier()); + clientGrant.setScope(Arrays.asList("create:resource", "create:organization_client_grants")); + clientGrant.setAllowAnyOrganization(true); + clientGrant.setOrganizationUsage("allow"); + + return api.clientGrants().create(client.getClientId(), resourceServer.getIdentifier(), new String[]{"create:resource", "create:organization_client_grants"}).execute().getBody(); + } + + private Client createNewClient(String orgId) throws Auth0Exception { + Client client = new Client("Test Client (" + System.currentTimeMillis() + ")"); + client.setDescription("This is just a test client."); + client.setOrganizationUsage("allow"); + client.setDefaultOrganization(new ClientDefaultOrganization(Arrays.asList("client_credentials"), orgId)); + + return api.clients().create(client).execute().getBody(); + } + + private Organization givenAnOrganization() throws Auth0Exception { + Organization organization = new Organization(); + organization.setName("test-organization"); + organization.setDisplayName("test-organization"); + + return api.organizations().create(organization).execute().getBody(); + } + + private ResourceServer givenAResourceServer() throws Auth0Exception { + ResourceServer resourceServer = new ResourceServer("https://www.tanyaisawesome.com"); + resourceServer.setName("tanyaisawesome"); + + return api.resourceServers().create(resourceServer).execute().getBody(); + } } diff --git a/src/test/java/com/auth0/client/mgmt/PromptsEntityTest.java b/src/test/java/com/auth0/client/mgmt/PromptsEntityTest.java new file mode 100644 index 000000000..435baf3c1 --- /dev/null +++ b/src/test/java/com/auth0/client/mgmt/PromptsEntityTest.java @@ -0,0 +1,191 @@ +package com.auth0.client.mgmt; + +import com.auth0.json.mgmt.prompts.Prompt; +import com.auth0.net.Request; +import com.auth0.net.client.HttpMethod; +import okhttp3.mockwebserver.RecordedRequest; +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.Map; + +import static com.auth0.client.MockServer.*; +import static com.auth0.client.RecordedRequestMatcher.hasHeader; +import static com.auth0.client.RecordedRequestMatcher.hasMethodAndPath; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; +import static com.auth0.AssertsUtil.verifyThrows; + +public class PromptsEntityTest extends BaseMgmtEntityTest{ + + @Test + public void shouldGetPrompts() throws Exception { + Request request = api.prompts().getPrompt(); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_PROMPT, 200); + Prompt response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/prompts")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + assertThat(response, is(notNullValue())); + } + + @Test + public void shouldThrowOnUpdatePromptsWhenPromptIsNull() throws Exception { + verifyThrows(IllegalArgumentException.class, + () -> api.prompts().updatePrompt(null), + "'prompt' cannot be null!"); + } + + @Test + public void shouldUpdatePrompts() throws Exception { + Prompt prompt = new Prompt(); + prompt.setIdentifierFirst(true); + prompt.setUniversalLoginExperience("new"); + prompt.setWebauthnPlatformFirstFactor(true); + + Request request = api.prompts().updatePrompt(prompt); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_PROMPT, 200); + Prompt response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PATCH, "/api/v2/prompts")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + assertThat(response, is(notNullValue())); + assertThat(response.isIdentifierFirst(), is(true)); + assertThat(response.getUniversalLoginExperience(), is("new")); + assertThat(response.isWebauthnPlatformFirstFactor(), is(true)); + } + + @Test + public void shouldThrowOnGetCustomTextWhenPromptIsNull() throws Exception { + verifyThrows(IllegalArgumentException.class, + () -> api.prompts().getCustomText(null, "en"), + "'prompt' cannot be null!"); + } + + @Test + public void shouldThrowOnGetCustomTextWhenLanguageIsNull() throws Exception { + verifyThrows(IllegalArgumentException.class, + () -> api.prompts().getCustomText("login", null), + "'language' cannot be null!"); + } + + @Test + public void shouldGetCustomText() throws Exception { + Request request = api.prompts().getCustomText("login", "en"); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_CUSTOM_TEXT_PROMPT, 200); + Object response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/prompts/login/custom-text/en")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + assertThat(response, is(notNullValue())); + } + + @Test + public void shouldThrowOnSetCustomTextWhenPromptIsNull() throws Exception { + verifyThrows(IllegalArgumentException.class, + () -> api.prompts().getCustomText(null, "en"), + "'prompt' cannot be null!"); + } + + @Test + public void shouldThrowOnSetCustomTextWhenLanguageIsNull() throws Exception { + verifyThrows(IllegalArgumentException.class, + () -> api.prompts().getCustomText("login", null), + "'language' cannot be null!"); + } + + @Test + public void shouldThrowOnSetCustomTextWhenCustomTextIsNull() throws Exception { + verifyThrows(IllegalArgumentException.class, + () -> api.prompts().setCustomText("login", "en", null), + "'customText' cannot be null!"); + } + + @Test + public void shouldSetCustomText() throws Exception { + Map signup = new HashMap<>(); + signup.put("description", "Sign up to access amazing features for my login domain"); + + Map customText = new HashMap<>(); + customText.put("signup", signup); + + Request request = api.prompts().setCustomText("login", "en", customText); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_CUSTOM_TEXT_PROMPT, 200); + request.execute(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PUT, "/api/v2/prompts/login/custom-text/en")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + } + + @Test + public void shouldThrowOnGetPartialsWhenPromptIsNull() throws Exception { + verifyThrows(IllegalArgumentException.class, + () -> api.prompts().getPartialsPrompt(null), + "'prompt' cannot be null!"); + } + + @Test + public void shouldGetPartials() throws Exception { + Request request = api.prompts().getPartialsPrompt("login"); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_PARTIALS_PROMPT, 200); + Object response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/prompts/login/partials")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + assertThat(response, is(notNullValue())); + } + + @Test + public void shouldThrowOnSetPartialsWhenPromptIsNull() throws Exception { + verifyThrows(IllegalArgumentException.class, + () -> api.prompts().setPartialsPrompt(null, new Object()), + "'prompt' cannot be null!"); + } + + @Test + public void shouldThrowOnSetPartialsWhenPartialsIsNull() throws Exception { + verifyThrows(IllegalArgumentException.class, + () -> api.prompts().setPartialsPrompt("login", null), + "'partials' cannot be null!"); + } + + @Test + public void shouldSetPartials() throws Exception { + Map partials = new HashMap<>(); + Request request = api.prompts().setPartialsPrompt("login", partials); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_PARTIALS_PROMPT, 200); + request.execute(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PUT, "/api/v2/prompts/login/partials")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + } +} diff --git a/src/test/java/com/auth0/client/mgmt/RefreshTokensEntityTest.java b/src/test/java/com/auth0/client/mgmt/RefreshTokensEntityTest.java new file mode 100644 index 000000000..69ef26841 --- /dev/null +++ b/src/test/java/com/auth0/client/mgmt/RefreshTokensEntityTest.java @@ -0,0 +1,61 @@ +package com.auth0.client.mgmt; + +import com.auth0.json.mgmt.refreshtokens.RefreshToken; +import com.auth0.net.Request; +import com.auth0.net.client.HttpMethod; +import okhttp3.mockwebserver.RecordedRequest; +import org.junit.jupiter.api.Test; + +import static com.auth0.AssertsUtil.verifyThrows; +import static com.auth0.client.MockServer.MGMT_REFRESH_TOKEN; +import static com.auth0.client.RecordedRequestMatcher.hasHeader; +import static com.auth0.client.RecordedRequestMatcher.hasMethodAndPath; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; + +public class RefreshTokensEntityTest extends BaseMgmtEntityTest{ + + @Test + public void shouldThrowOnGetWithNullRefreshTokenId() { + verifyThrows(IllegalArgumentException.class, + () -> api.refreshTokens().get(null), + "'refresh token ID' cannot be null!"); + } + + @Test + public void shouldGetRefreshToken() throws Exception { + Request request = api.refreshTokens().get("refresh_token_ID"); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_REFRESH_TOKEN, 200); + RefreshToken response =request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/refresh-tokens/refresh_token_ID")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + assertThat(response, is(notNullValue())); + } + + @Test + public void shouldThrowOnDeleteWithNullRefreshTokenId() { + verifyThrows(IllegalArgumentException.class, + () -> api.refreshTokens().delete(null), + "'refresh token ID' cannot be null!"); + } + + @Test + public void shouldDeleteRefreshToken() throws Exception { + Request request = api.refreshTokens().delete("refresh_token_ID"); + assertThat(request, is(notNullValue())); + + server.noContentResponse(); + request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/refresh-tokens/refresh_token_ID")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + } +} diff --git a/src/test/java/com/auth0/client/mgmt/ResourceServerEntityTest.java b/src/test/java/com/auth0/client/mgmt/ResourceServerEntityTest.java index 53664e864..e4f7d9fe8 100644 --- a/src/test/java/com/auth0/client/mgmt/ResourceServerEntityTest.java +++ b/src/test/java/com/auth0/client/mgmt/ResourceServerEntityTest.java @@ -1,21 +1,21 @@ package com.auth0.client.mgmt; import com.auth0.client.mgmt.filter.ResourceServersFilter; -import com.auth0.json.mgmt.ResourceServer; -import com.auth0.json.mgmt.ResourceServersPage; -import com.auth0.json.mgmt.Scope; +import com.auth0.json.mgmt.resourceserver.ResourceServer; +import com.auth0.json.mgmt.resourceserver.ResourceServersPage; +import com.auth0.json.mgmt.resourceserver.Scope; import com.auth0.net.Request; +import com.auth0.net.client.HttpMethod; import okhttp3.mockwebserver.RecordedRequest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.Collections; -import java.util.List; import java.util.Map; import static com.auth0.client.MockServer.*; import static com.auth0.client.RecordedRequestMatcher.*; -import static org.hamcrest.Matchers.*; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; public class ResourceServerEntityTest extends BaseMgmtEntityTest { @@ -26,10 +26,10 @@ public void shouldListResourceServerWithoutFilter() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_RESOURCE_SERVERS_LIST, 200); - ResourceServersPage response = request.execute(); + ResourceServersPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/resource-servers")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/resource-servers")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -44,10 +44,10 @@ public void shouldListResourceServerWithPage() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_RESOURCE_SERVERS_LIST, 200); - ResourceServersPage response = request.execute(); + ResourceServersPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/resource-servers")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/resource-servers")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("page", "23")); @@ -64,10 +64,10 @@ public void shouldListResourceServerWithTotals() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_RESOURCE_SERVERS_PAGED_LIST, 200); - ResourceServersPage response = request.execute(); + ResourceServersPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/resource-servers")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/resource-servers")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("include_totals", "true")); @@ -81,22 +81,49 @@ public void shouldListResourceServerWithTotals() throws Exception { } @Test - public void shouldListResourceServers() throws Exception { - @SuppressWarnings("deprecation") - Request> request = api.resourceServers().list(); - + public void shouldListResourceServerWithIdentifiers() throws Exception { + ResourceServersFilter filter = new ResourceServersFilter().withIdentifiers("identifier"); + Request request = api.resourceServers().list(filter); assertThat(request, is(notNullValue())); - server.jsonResponse(MGMT_RESOURCE_SERVERS_LIST, 200); - List response = request.execute(); + server.jsonResponse(MGMT_RESOURCE_SERVERS_PAGED_LIST, 200); + ResourceServersPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/resource-servers")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/resource-servers")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + assertThat(recordedRequest, hasQueryParameter("identifiers", "identifier")); + + assertThat(response, is(notNullValue())); + assertThat(response.getItems(), hasSize(2)); + assertThat(response.getStart(), is(0)); + assertThat(response.getLength(), is(14)); + assertThat(response.getTotal(), is(14)); + assertThat(response.getLimit(), is(50)); + } + @Test + public void shouldListResourceServerWithCheckpointPagination() throws Exception { + ResourceServersFilter filter = new ResourceServersFilter().withCheckpointPagination("tokenId2", 5); + Request request = api.resourceServers().list(filter); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_RESOURCE_SERVERS_PAGED_LIST, 200); + ResourceServersPage response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/resource-servers")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + assertThat(recordedRequest, hasQueryParameter("from", "tokenId2")); + assertThat(recordedRequest, hasQueryParameter("take", "5")); assertThat(response, is(notNullValue())); - assertThat(response, hasSize(2)); + assertThat(response.getItems(), hasSize(2)); + assertThat(response.getStart(), is(0)); + assertThat(response.getLength(), is(14)); + assertThat(response.getTotal(), is(14)); + assertThat(response.getLimit(), is(50)); } @Test @@ -118,10 +145,10 @@ public void shouldUpdateResourceServer() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_RESOURCE_SERVER, 200); - ResourceServer response = request.execute(); + ResourceServer response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("PATCH", "/api/v2/resource-servers/23445566abab")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PATCH, "/api/v2/resource-servers/23445566abab")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -139,10 +166,10 @@ public void shouldGetResourceServerById() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_RESOURCE_SERVER, 200); - ResourceServer response = request.execute(); + ResourceServer response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/resource-servers/23445566abab")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/resource-servers/23445566abab")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -156,10 +183,10 @@ public void shouldCreateResourceServer() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_RESOURCE_SERVER, 200); - ResourceServer response = request.execute(); + ResourceServer response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/api/v2/resource-servers")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/resource-servers")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -177,10 +204,10 @@ public void shouldDeleteResourceServer() throws Exception { assertThat(request, is(notNullValue())); server.emptyResponse(200); - request.execute(); + request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("DELETE", "/api/v2/resource-servers/23445566abab")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/resource-servers/23445566abab")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); } diff --git a/src/test/java/com/auth0/client/mgmt/RolesEntityTest.java b/src/test/java/com/auth0/client/mgmt/RolesEntityTest.java index 5c2cfe9d3..77c48cc1d 100644 --- a/src/test/java/com/auth0/client/mgmt/RolesEntityTest.java +++ b/src/test/java/com/auth0/client/mgmt/RolesEntityTest.java @@ -2,20 +2,22 @@ import com.auth0.client.mgmt.filter.PageFilter; import com.auth0.client.mgmt.filter.RolesFilter; -import com.auth0.json.mgmt.Permission; -import com.auth0.json.mgmt.PermissionsPage; -import com.auth0.json.mgmt.Role; -import com.auth0.json.mgmt.RolesPage; +import com.auth0.json.mgmt.permissions.Permission; +import com.auth0.json.mgmt.permissions.PermissionsPage; +import com.auth0.json.mgmt.roles.Role; +import com.auth0.json.mgmt.roles.RolesPage; import com.auth0.json.mgmt.users.UsersPage; import com.auth0.net.Request; +import com.auth0.net.client.HttpMethod; import okhttp3.mockwebserver.RecordedRequest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; +import static com.auth0.AssertsUtil.verifyThrows; import static com.auth0.client.MockServer.*; import static com.auth0.client.RecordedRequestMatcher.*; import static org.hamcrest.MatcherAssert.assertThat; @@ -29,10 +31,10 @@ public void shouldListRolesWithoutFilter() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_ROLES_LIST, 200); - RolesPage response = request.execute(); + RolesPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/roles")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/roles")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -47,10 +49,10 @@ public void shouldListRolesWithPage() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_ROLES_LIST, 200); - RolesPage response = request.execute(); + RolesPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/roles")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/roles")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("page", "23")); @@ -67,10 +69,10 @@ public void shouldListRolesWithTotals() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_ROLES_PAGED_LIST, 200); - RolesPage response = request.execute(); + RolesPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/roles")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/roles")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("include_totals", "true")); @@ -89,10 +91,10 @@ public void shouldGetRole() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_ROLE, 200); - Role response = request.execute(); + Role response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/roles/1")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/roles/1")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -101,16 +103,16 @@ public void shouldGetRole() throws Exception { @Test public void shouldThrowOnGetRoleWithNullRoleId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'role id' cannot be null!"); - api.roles().get(null); + verifyThrows(IllegalArgumentException.class, + () -> api.roles().get(null), + "'role id' cannot be null!"); } @Test public void shouldThrowOnCreateRoleWithNullData() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'user' cannot be null!"); - api.users().create(null); + verifyThrows(IllegalArgumentException.class, + () -> api.users().create(null), + "'user' cannot be null!"); } @Test @@ -121,10 +123,10 @@ public void shouldCreateRole() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_ROLE, 200); - Role response = request.execute(); + Role response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/api/v2/roles")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/roles")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -137,16 +139,16 @@ public void shouldCreateRole() throws Exception { @Test public void shouldThrowOnUpdateRoleWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'role id' cannot be null!"); - api.roles().update(null, new Role()); + verifyThrows(IllegalArgumentException.class, + () -> api.roles().update(null, new Role()), + "'role id' cannot be null!"); } @Test public void shouldThrowOnUpdateRoleWithNullData() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'role' cannot be null!"); - api.roles().update("1", null); + verifyThrows(IllegalArgumentException.class, + () -> api.roles().update("1", null), + "'role' cannot be null!"); } @Test @@ -157,10 +159,10 @@ public void shouldUpdateRole() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_ROLE, 200); - Role response = request.execute(); + Role response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("PATCH", "/api/v2/roles/1")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PATCH, "/api/v2/roles/1")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -173,9 +175,9 @@ public void shouldUpdateRole() throws Exception { @Test public void shouldThrowOnDeleteRoleWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'role id' cannot be null!"); - api.roles().delete(null); + verifyThrows(IllegalArgumentException.class, + () -> api.roles().delete(null), + "'role id' cannot be null!"); } @Test @@ -184,19 +186,19 @@ public void shouldDeleteRole() throws Exception { assertThat(request, is(notNullValue())); server.emptyResponse(200); - request.execute(); + request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("DELETE", "/api/v2/roles/1")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/roles/1")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); } @Test public void shouldThrowOnListUsersWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'role id' cannot be null!"); - api.roles().listUsers(null, null); + verifyThrows(IllegalArgumentException.class, + () -> api.roles().listUsers(null, null), + "'role id' cannot be null!"); } @Test @@ -205,10 +207,10 @@ public void shouldListUsersWithoutFilter() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_ROLE_USERS_PAGED_LIST, 200); - UsersPage response = request.execute(); + UsersPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/roles/1/users")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/roles/1/users")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -223,10 +225,10 @@ public void shouldListUsersWithPage() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_ROLE_USERS_PAGED_LIST, 200); - UsersPage response = request.execute(); + UsersPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/roles/1/users")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/roles/1/users")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("page", "23")); @@ -243,10 +245,10 @@ public void shouldListUsersWithTotals() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_ROLE_USERS_PAGED_LIST, 200); - UsersPage response = request.execute(); + UsersPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/roles/1/users")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/roles/1/users")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("include_totals", "true")); @@ -266,10 +268,10 @@ public void shouldListUsersWithCheckpointPaging() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_ROLE_USERS_CHECKPOINT_PAGED_LIST, 200); - UsersPage response = request.execute(); + UsersPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/roles/1/users")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/roles/1/users")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("take", "2")); @@ -286,23 +288,23 @@ public void shouldListUsersWithCheckpointPaging() throws Exception { @Test public void shouldThrowOnAssignUsersWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'role id' cannot be null!"); - api.roles().assignUsers(null, Collections.emptyList()); + verifyThrows(IllegalArgumentException.class, + () -> api.roles().assignUsers(null, Collections.emptyList()), + "'role id' cannot be null!"); } @Test public void shouldThrowOnAssignUsersWithNullList() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'user ids' cannot be null!"); - api.roles().assignUsers("1", null); + verifyThrows(IllegalArgumentException.class, + () -> api.roles().assignUsers("1", null), + "'user ids' cannot be null!"); } @Test public void shouldThrowOnAssignUsersWithEmptyList() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'user ids' cannot be empty!"); - api.roles().assignUsers("1", Collections.emptyList()); + verifyThrows(IllegalArgumentException.class, + () -> api.roles().assignUsers("1", Collections.emptyList()), + "'user ids' cannot be empty!"); } @Test @@ -313,10 +315,10 @@ public void shouldAssignUsers() throws Exception { assertThat(request, is(notNullValue())); server.emptyResponse(200); - Object response = request.execute(); + Object response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/api/v2/roles/1/users")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/roles/1/users")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -333,10 +335,10 @@ public void shouldListPermissionsWithoutFilter() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_ROLE_PERMISSIONS_PAGED_LIST, 200); - PermissionsPage response = request.execute(); + PermissionsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/roles/1/permissions")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/roles/1/permissions")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -351,10 +353,10 @@ public void shouldListPermissionsWithPage() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_ROLE_PERMISSIONS_PAGED_LIST, 200); - PermissionsPage response = request.execute(); + PermissionsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/roles/1/permissions")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/roles/1/permissions")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("page", "23")); @@ -371,10 +373,10 @@ public void shouldListPermissionsWithTotal() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_ROLE_PERMISSIONS_PAGED_LIST, 200); - PermissionsPage response = request.execute(); + PermissionsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/roles/1/permissions")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/roles/1/permissions")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("include_totals", "true")); @@ -389,23 +391,23 @@ public void shouldListPermissionsWithTotal() throws Exception { @Test public void shouldThrowOnAddPermissionsWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'role id' cannot be null!"); - api.roles().addPermissions(null, Collections.emptyList()); + verifyThrows(IllegalArgumentException.class, + () -> api.roles().addPermissions(null, Collections.emptyList()), + "'role id' cannot be null!"); } @Test public void shouldThrowOnAddPermissionsWithNullList() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'permissions' cannot be null!"); - api.roles().addPermissions("1", null); + verifyThrows(IllegalArgumentException.class, + () -> api.roles().addPermissions("1", null), + "'permissions' cannot be null!"); } @Test public void shouldThrowOnAddPermissionsWithEmptyList() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'permissions' cannot be empty!"); - api.roles().addPermissions("1", Collections.emptyList()); + verifyThrows(IllegalArgumentException.class, + () -> api.roles().addPermissions("1", Collections.emptyList()), + "'permissions' cannot be empty!"); } @Test @@ -418,10 +420,10 @@ public void shouldAddPermissions() throws Exception { assertThat(request, is(notNullValue())); server.emptyResponse(200); - Object response = request.execute(); + Object response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/api/v2/roles/1/permissions")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/roles/1/permissions")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -434,23 +436,23 @@ public void shouldAddPermissions() throws Exception { @Test public void shouldThrowOnRemovePermissionsWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'role id' cannot be null!"); - api.roles().removePermissions(null, Collections.emptyList()); + verifyThrows(IllegalArgumentException.class, + () -> api.roles().removePermissions(null, Collections.emptyList()), + "'role id' cannot be null!"); } @Test public void shouldThrowOnRemovePermissionsWithNullList() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'permissions' cannot be null!"); - api.roles().removePermissions("1", null); + verifyThrows(IllegalArgumentException.class, + () -> api.roles().removePermissions("1", null), + "'permissions' cannot be null!"); } @Test public void shouldThrowOnRemovePermissionsWithEmptyList() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'permissions' cannot be empty!"); - api.roles().removePermissions("1", Collections.emptyList()); + verifyThrows(IllegalArgumentException.class, + () -> api.roles().removePermissions("1", Collections.emptyList()), + "'permissions' cannot be empty!"); } @Test @@ -463,10 +465,10 @@ public void shouldRemovePermissions() throws Exception { assertThat(request, is(notNullValue())); server.emptyResponse(200); - Object response = request.execute(); + Object response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("DELETE", "/api/v2/roles/1/permissions")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/roles/1/permissions")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); diff --git a/src/test/java/com/auth0/client/mgmt/RulesConfigsEntityTest.java b/src/test/java/com/auth0/client/mgmt/RulesConfigsEntityTest.java index 71ba600f6..43fd23de9 100644 --- a/src/test/java/com/auth0/client/mgmt/RulesConfigsEntityTest.java +++ b/src/test/java/com/auth0/client/mgmt/RulesConfigsEntityTest.java @@ -1,18 +1,20 @@ package com.auth0.client.mgmt; -import com.auth0.json.mgmt.RulesConfig; +import com.auth0.json.mgmt.rules.RulesConfig; import com.auth0.net.Request; +import com.auth0.net.client.HttpMethod; import okhttp3.mockwebserver.RecordedRequest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.List; import java.util.Map; +import static com.auth0.AssertsUtil.verifyThrows; import static com.auth0.client.MockServer.*; import static com.auth0.client.RecordedRequestMatcher.hasHeader; import static com.auth0.client.RecordedRequestMatcher.hasMethodAndPath; -import static org.hamcrest.Matchers.*; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; public class RulesConfigsEntityTest extends BaseMgmtEntityTest { @@ -22,10 +24,10 @@ public void shouldListRules() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_RULES_CONFIGS_LIST, 200); - List response = request.execute(); + List response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/rules-configs")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/rules-configs")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -39,7 +41,7 @@ public void shouldReturnEmptyRulesConfigs() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_EMPTY_LIST, 200); - List response = request.execute(); + List response = request.execute().getBody(); assertThat(response, is(notNullValue())); assertThat(response, is(emptyCollectionOf(RulesConfig.class))); @@ -47,9 +49,9 @@ public void shouldReturnEmptyRulesConfigs() throws Exception { @Test public void shouldThrowOnDeleteRulesConfigWithNullKey() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'rules config key' cannot be null!"); - api.rulesConfigs().delete(null); + verifyThrows(IllegalArgumentException.class, + () -> api.rulesConfigs().delete(null), + "'rules config key' cannot be null!"); } @Test @@ -58,26 +60,26 @@ public void shouldDeleteRulesConfig() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_RULE, 200); - request.execute(); + request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("DELETE", "/api/v2/rules-configs/1")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/rules-configs/1")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); } @Test public void shouldThrowOnUpdateRulesConfigWithNullKey() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'rules config key' cannot be null!"); - api.rulesConfigs().update(null, new RulesConfig("my-value")); + verifyThrows(IllegalArgumentException.class, + () -> api.rulesConfigs().update(null, new RulesConfig("my-value")), + "'rules config key' cannot be null!"); } @Test public void shouldThrowOnUpdateRulesConfigWithNullData() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'rules config' cannot be null!"); - api.rulesConfigs().update("1", null); + verifyThrows(IllegalArgumentException.class, + () -> api.rulesConfigs().update("1", null), + "'rules config' cannot be null!"); } @Test @@ -86,10 +88,10 @@ public void shouldUpdateRulesConfig() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_CONNECTION, 200); - RulesConfig response = request.execute(); + RulesConfig response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("PUT", "/api/v2/rules-configs/1")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PUT, "/api/v2/rules-configs/1")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); diff --git a/src/test/java/com/auth0/client/mgmt/RulesEntityTest.java b/src/test/java/com/auth0/client/mgmt/RulesEntityTest.java index 15ae49ad8..33e154222 100644 --- a/src/test/java/com/auth0/client/mgmt/RulesEntityTest.java +++ b/src/test/java/com/auth0/client/mgmt/RulesEntityTest.java @@ -1,50 +1,33 @@ package com.auth0.client.mgmt; import com.auth0.client.mgmt.filter.RulesFilter; -import com.auth0.json.mgmt.Rule; -import com.auth0.json.mgmt.RulesPage; +import com.auth0.json.mgmt.rules.Rule; +import com.auth0.json.mgmt.rules.RulesPage; import com.auth0.net.Request; +import com.auth0.net.client.HttpMethod; import okhttp3.mockwebserver.RecordedRequest; -import org.junit.Test; +import org.junit.jupiter.api.Test; -import java.util.List; import java.util.Map; +import static com.auth0.AssertsUtil.verifyThrows; import static com.auth0.client.MockServer.*; import static com.auth0.client.RecordedRequestMatcher.*; -import static org.hamcrest.Matchers.*; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; public class RulesEntityTest extends BaseMgmtEntityTest { - @Test - public void shouldListRules() throws Exception { - @SuppressWarnings("deprecation") - Request> request = api.rules().list(null); - assertThat(request, is(notNullValue())); - - server.jsonResponse(MGMT_RULES_LIST, 200); - List response = request.execute(); - RecordedRequest recordedRequest = server.takeRequest(); - - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/rules")); - assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); - assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); - - assertThat(response, is(notNullValue())); - assertThat(response, hasSize(2)); - } - @Test public void shouldListRulesWithoutFilter() throws Exception { Request request = api.rules().listAll(null); assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_RULES_LIST, 200); - RulesPage response = request.execute(); + RulesPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/rules")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/rules")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -52,70 +35,6 @@ public void shouldListRulesWithoutFilter() throws Exception { assertThat(response.getItems(), hasSize(2)); } - @Test - public void shouldListRulesWithEnabled() throws Exception { - RulesFilter filter = new RulesFilter().withEnabled(true); - - @SuppressWarnings("deprecation") - Request> request = api.rules().list(filter); - assertThat(request, is(notNullValue())); - - server.jsonResponse(MGMT_RULES_LIST, 200); - List response = request.execute(); - RecordedRequest recordedRequest = server.takeRequest(); - - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/rules")); - assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); - assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); - assertThat(recordedRequest, hasQueryParameter("enabled", "true")); - - assertThat(response, is(notNullValue())); - assertThat(response, hasSize(2)); - } - - @Test - public void shouldListRulesWithFields() throws Exception { - RulesFilter filter = new RulesFilter().withFields("some,random,fields", true); - - @SuppressWarnings("deprecation") - Request> request = api.rules().list(filter); - assertThat(request, is(notNullValue())); - - server.jsonResponse(MGMT_RULES_LIST, 200); - List response = request.execute(); - RecordedRequest recordedRequest = server.takeRequest(); - - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/rules")); - assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); - assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); - assertThat(recordedRequest, hasQueryParameter("fields", "some,random,fields")); - assertThat(recordedRequest, hasQueryParameter("include_fields", "true")); - - assertThat(response, is(notNullValue())); - assertThat(response, hasSize(2)); - } - - @Test - public void shouldNotListRulesWithTotals() throws Exception { - RulesFilter filter = new RulesFilter().withTotals(true); - - @SuppressWarnings("deprecation") - Request> request = api.rules().list(filter); - assertThat(request, is(notNullValue())); - - server.jsonResponse(MGMT_RULES_LIST, 200); - List response = request.execute(); - RecordedRequest recordedRequest = server.takeRequest(); - - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/rules")); - assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); - assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); - assertThat(recordedRequest, not(hasQueryParameter("include_totals"))); - - assertThat(response, is(notNullValue())); - assertThat(response, hasSize(2)); - } - @Test public void shouldListRulesWithPage() throws Exception { RulesFilter filter = new RulesFilter().withPage(23, 5); @@ -123,10 +42,10 @@ public void shouldListRulesWithPage() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_RULES_LIST, 200); - RulesPage response = request.execute(); + RulesPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/rules")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/rules")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("page", "23")); @@ -143,10 +62,10 @@ public void shouldListRulesWithTotals() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_RULES_PAGED_LIST, 200); - RulesPage response = request.execute(); + RulesPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/rules")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/rules")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("include_totals", "true")); @@ -159,24 +78,11 @@ public void shouldListRulesWithTotals() throws Exception { assertThat(response.getLimit(), is(50)); } - @Test - public void shouldReturnEmptyRules() throws Exception { - @SuppressWarnings("deprecation") - Request> request = api.rules().list(null); - assertThat(request, is(notNullValue())); - - server.jsonResponse(MGMT_EMPTY_LIST, 200); - List response = request.execute(); - - assertThat(response, is(notNullValue())); - assertThat(response, is(emptyCollectionOf(Rule.class))); - } - @Test public void shouldThrowOnGetRuleWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'rule id' cannot be null!"); - api.rules().get(null, null); + verifyThrows(IllegalArgumentException.class, + () -> api.rules().get(null, null), + "'rule id' cannot be null!"); } @Test @@ -185,10 +91,10 @@ public void shouldGetRule() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_RULE, 200); - Rule response = request.execute(); + Rule response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/rules/1")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/rules/1")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -202,10 +108,10 @@ public void shouldGetRuleWithFields() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_RULE, 200); - Rule response = request.execute(); + Rule response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/rules/1")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/rules/1")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("fields", "some,random,fields")); @@ -216,9 +122,9 @@ public void shouldGetRuleWithFields() throws Exception { @Test public void shouldThrowOnCreateRuleWithNullData() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'rule' cannot be null!"); - api.rules().create(null); + verifyThrows(IllegalArgumentException.class, + () -> api.rules().create(null), + "'rule' cannot be null!"); } @Test @@ -227,10 +133,10 @@ public void shouldCreateRule() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_RULE, 200); - Rule response = request.execute(); + Rule response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/api/v2/rules")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/rules")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -244,9 +150,9 @@ public void shouldCreateRule() throws Exception { @Test public void shouldThrowOnDeleteRuleWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'rule id' cannot be null!"); - api.rules().delete(null); + verifyThrows(IllegalArgumentException.class, + () -> api.rules().delete(null), + "'rule id' cannot be null!"); } @Test @@ -255,26 +161,26 @@ public void shouldDeleteRule() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_RULE, 200); - request.execute(); + request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("DELETE", "/api/v2/rules/1")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/rules/1")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); } @Test public void shouldThrowOnUpdateRuleWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'rule id' cannot be null!"); - api.rules().update(null, new Rule("my-rule", "function(){}")); + verifyThrows(IllegalArgumentException.class, + () -> api.rules().update(null, new Rule("my-rule", "function(){}")), + "'rule id' cannot be null!"); } @Test public void shouldThrowOnUpdateRuleWithNullData() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'rule' cannot be null!"); - api.rules().update("1", null); + verifyThrows(IllegalArgumentException.class, + () -> api.rules().update("1", null), + "'rule' cannot be null!"); } @Test @@ -283,10 +189,10 @@ public void shouldUpdateRule() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_CONNECTION, 200); - Rule response = request.execute(); + Rule response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("PATCH", "/api/v2/rules/1")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PATCH, "/api/v2/rules/1")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); diff --git a/src/test/java/com/auth0/client/mgmt/SelfServiceProfilesEntityTest.java b/src/test/java/com/auth0/client/mgmt/SelfServiceProfilesEntityTest.java new file mode 100644 index 000000000..feaaeedfb --- /dev/null +++ b/src/test/java/com/auth0/client/mgmt/SelfServiceProfilesEntityTest.java @@ -0,0 +1,326 @@ +package com.auth0.client.mgmt; + +import com.auth0.client.mgmt.filter.PageBasedPaginationFilter; +import com.auth0.json.mgmt.selfserviceprofiles.*; +import com.auth0.net.Request; +import com.auth0.net.client.HttpMethod; +import okhttp3.mockwebserver.RecordedRequest; +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.Map; + +import static com.auth0.AssertsUtil.verifyThrows; +import static com.auth0.client.MockServer.*; +import static com.auth0.client.RecordedRequestMatcher.*; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; + +public class SelfServiceProfilesEntityTest extends BaseMgmtEntityTest { + + @Test + public void shouldGetSelfServiceProfilesWithoutFilter() throws Exception{ + Request request = api.selfServiceProfiles().get(null); + assertThat(request, is(notNullValue())); + + server.jsonResponse(SELF_SERVICE_PROFILES_LIST, 200); + SelfServiceProfileResponsePage response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/self-service-profiles")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + assertThat(response, is(notNullValue())); + assertThat(response.getItems(), hasSize(3)); + } + + @Test + public void shouldGetSelfServiceProfilesWithPage() throws Exception { + PageBasedPaginationFilter filter = new PageBasedPaginationFilter().withPage(1, 5); + Request request = api.selfServiceProfiles().get(filter); + assertThat(request, is(notNullValue())); + + server.jsonResponse(SELF_SERVICE_PROFILES_LIST, 200); + SelfServiceProfileResponsePage response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/self-service-profiles")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + assertThat(recordedRequest, hasQueryParameter("page", "1")); + assertThat(recordedRequest, hasQueryParameter("per_page", "5")); + + assertThat(response, is(notNullValue())); + assertThat(response.getItems(), hasSize(3)); + } + + @Test + public void shouldGetSelfServiceProfilesWithTotals() throws Exception { + PageBasedPaginationFilter filter = new PageBasedPaginationFilter().withTotals(true); + Request request = api.selfServiceProfiles().get(filter); + assertThat(request, is(notNullValue())); + + server.jsonResponse(SELF_SERVICE_PROFILES_LIST, 200); + SelfServiceProfileResponsePage response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/self-service-profiles")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + assertThat(recordedRequest, hasQueryParameter("include_totals", "true")); + + assertThat(response, is(notNullValue())); + assertThat(response.getItems(), hasSize(3)); + } + + @Test + public void shouldThrowOnCreateWhenSelfServiceProfileIsNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.selfServiceProfiles().create(null), "'self service profile' cannot be null!"); + } + + @Test + public void shouldThrowOnCreateWhenNameInSelfServiceProfileIsNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.selfServiceProfiles().create(new SelfServiceProfile()), "'name' cannot be null!"); + } + + @Test + public void shouldCreateSelfServiceProfile() throws Exception { + SelfServiceProfile profile = new SelfServiceProfile(); + profile.setName("Test"); + profile.setDescription("This is for Test"); + Request request = api.selfServiceProfiles().create(profile); + assertThat(request, is(notNullValue())); + + server.jsonResponse(SELF_SERVICE_PROFILE_RESPONSE, 201); + SelfServiceProfileResponse response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/self-service-profiles")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + Map body = bodyFromRequest(recordedRequest); + assertThat(body.size(), is(2)); + assertThat(body, hasEntry("name", "Test")); + assertThat(body, hasEntry("description", "This is for Test")); + + assertThat(response, is(notNullValue())); + } + + @Test + public void shouldThrowOnGetByIdWhenIdIsNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.selfServiceProfiles().getById(null), "'id' cannot be null!"); + } + + @Test + public void shouldGetSelfServiceProfileById() throws Exception { + Request request = api.selfServiceProfiles().getById("id"); + assertThat(request, is(notNullValue())); + + server.jsonResponse(SELF_SERVICE_PROFILE_RESPONSE, 200); + SelfServiceProfileResponse response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/self-service-profiles/id")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + assertThat(response, is(notNullValue())); + } + + @Test + public void shouldThrowOnDeleteWhenIdIsNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.selfServiceProfiles().delete(null), "'id' cannot be null!"); + } + + @Test + public void shouldDeleteSelfServiceProfile() throws Exception { + Request request = api.selfServiceProfiles().delete("id"); + assertThat(request, is(notNullValue())); + + server.jsonResponse(SELF_SERVICE_PROFILE_RESPONSE, 200); + request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/self-service-profiles/id")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + } + + @Test + public void shouldThrowOnUpdateWhenIdIsNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.selfServiceProfiles().update(new SelfServiceProfile(), null), "'id' cannot be null!"); + } + + @Test + public void shouldThrowOnUpdateWhenSelfServiceProfileIsNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.selfServiceProfiles().update(null, "id"), "'self service profile' cannot be null!"); + } + + @Test + public void shouldUpdateSelfServiceProfile() throws Exception { + SelfServiceProfile profile = new SelfServiceProfile(); + profile.setDescription("This is Test is updated"); + Request request = api.selfServiceProfiles().update(profile, "id"); + assertThat(request, is(notNullValue())); + + server.jsonResponse(SELF_SERVICE_PROFILE_RESPONSE, 200); + SelfServiceProfileResponse response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PATCH, "/api/v2/self-service-profiles/id")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + Map body = bodyFromRequest(recordedRequest); + assertThat(body.size(), is(1)); + assertThat(body, hasEntry("description", "This is Test is updated")); + + assertThat(response, is(notNullValue())); + } + + @Test + public void shouldThrowOnGetCustomTextWhenIdIsNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.selfServiceProfiles().getCustomText(null, "language", "page"), "'id' cannot be null!"); + } + + @Test + public void shouldThrowOnGetCustomTextWhenLanguageIsNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.selfServiceProfiles().getCustomText("id", null, "page"), "'language' cannot be null!"); + } + + @Test + public void shouldThrowOnGetCustomTextWhenPageIsNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.selfServiceProfiles().getCustomText("id", "language", null), "'page' cannot be null!"); + } + + @Test + public void shouldGetCustomText() throws Exception { + Request request = api.selfServiceProfiles().getCustomText("id", "language", "page"); + assertThat(request, is(notNullValue())); + + server.jsonResponse(SELF_SERVICE_PROFILE_CUSTOM_TEXT, 200); + Object response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/self-service-profiles/id/custom-text/language/page")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + assertThat(response, is(notNullValue())); + } + + @Test + public void shouldThrowOnSetCustomTextWhenIdIsNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.selfServiceProfiles().setCustomText(null, "language", "page", new Object()), "'id' cannot be null!"); + } + + @Test + public void shouldThrowOnSetCustomTextWhenLanguageIsNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.selfServiceProfiles().setCustomText("id", null, "page", new Object()), "'language' cannot be null!"); + } + + @Test + public void shouldThrowOnSetCustomTextWhenPageIsNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.selfServiceProfiles().setCustomText("id", "language", null, new Object()), "'page' cannot be null!"); + } + + @Test + public void shouldThrowOnSetCustomTextWhenCustomTextIsNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.selfServiceProfiles().setCustomText("id", "language", "page", null), "'custom text' cannot be null!"); + } + + @Test + public void shouldSetCustomText() throws Exception { + Map customText = new HashMap<>(); + customText.put("introduction", "Welcome! With only a few steps"); + Request request = api.selfServiceProfiles().setCustomText("id", "language", "page", customText); + assertThat(request, is(notNullValue())); + + server.jsonResponse(SELF_SERVICE_PROFILE_CUSTOM_TEXT, 200); + Object response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PUT, "/api/v2/self-service-profiles/id/custom-text/language/page")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + assertThat(response, is(notNullValue())); + } + + @Test + public void shouldThrowOnCreateSsoAccessTicketWhenIdIsNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.selfServiceProfiles().createSsoAccessTicket(null, new SsoAccessTicketRequest()), "'id' cannot be null!"); + } + + @Test + public void shouldThrowOnCreateSsoAccessTicketWhenPayloadIsNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.selfServiceProfiles().createSsoAccessTicket("id", null), "'request body' cannot be null!"); + } + + @Test + public void shouldCreateSsoAccessTicket() throws Exception{ + SsoAccessTicketRequest requestBody = new SsoAccessTicketRequest(); + requestBody.setConnectionId("test-connection"); + ProvisioningConfig provisioningConfig = new ProvisioningConfig(); + GoogleWorkspaceProvisioningConfig googleWorkspace = new GoogleWorkspaceProvisioningConfig(); + googleWorkspace.setSyncUsers(true); + provisioningConfig.setGoogleWorkspace(googleWorkspace); + requestBody.setProvisioningConfig(provisioningConfig); + + Request request = api.selfServiceProfiles().createSsoAccessTicket("id", requestBody); + assertThat(request, is(notNullValue())); + + server.jsonResponse(SELF_SERVICE_PROFILE_SSO_TICKET, 200); + SsoAccessTicketResponse response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/self-service-profiles/id/sso-ticket")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + assertThat(response, is(notNullValue())); + } + + @Test + public void shouldThrowOnRevokeSsoTicketWhenIdIsNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.selfServiceProfiles().revokeSsoTicket(null, "ticketId"), "'id' cannot be null!"); + } + + @Test + public void shouldThrowOnRevokeSsoTicketWhenTicketIdIsNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.selfServiceProfiles().revokeSsoTicket("id", null), "'ticket id' cannot be null!"); + } + + @Test + public void shouldRevokeSsoTicket() throws Exception{ + Request request = api.selfServiceProfiles().revokeSsoTicket("id", "ticketId"); + assertThat(request, is(notNullValue())); + + server.noContentResponse(); + request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/self-service-profiles/id/sso-ticket/ticketId/revoke")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + } +} diff --git a/src/test/java/com/auth0/client/mgmt/SessionsEntityTest.java b/src/test/java/com/auth0/client/mgmt/SessionsEntityTest.java new file mode 100644 index 000000000..795c544c6 --- /dev/null +++ b/src/test/java/com/auth0/client/mgmt/SessionsEntityTest.java @@ -0,0 +1,81 @@ +package com.auth0.client.mgmt; + +import com.auth0.json.mgmt.sessions.Session; +import com.auth0.net.Request; +import com.auth0.net.client.HttpMethod; +import okhttp3.mockwebserver.RecordedRequest; +import org.junit.jupiter.api.Test; + +import static com.auth0.AssertsUtil.verifyThrows; +import static com.auth0.client.MockServer.MGMT_SESSION; +import static com.auth0.client.RecordedRequestMatcher.hasHeader; +import static com.auth0.client.RecordedRequestMatcher.hasMethodAndPath; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; + +public class SessionsEntityTest extends BaseMgmtEntityTest{ + @Test + public void getSessionShouldThrowOnNullSessionId() { + verifyThrows(IllegalArgumentException.class, + () -> api.sessions().get(null), + "'session ID' cannot be null!"); + } + + @Test + public void shouldGetSession() throws Exception { + Request request = api.sessions().get("session_ID"); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_SESSION, 200); + Session response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/sessions/session_ID")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + assertThat(response, is(notNullValue())); + } + + @Test + public void deleteSessionShouldThrowOnNullSessionId() { + verifyThrows(IllegalArgumentException.class, + () -> api.sessions().delete(null), + "'session ID' cannot be null!"); + } + + @Test + public void shouldDeleteSession() throws Exception { + Request request = api.sessions().delete("session_ID"); + assertThat(request, is(notNullValue())); + + server.noContentResponse(); + request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/sessions/session_ID")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + } + + @Test + public void revokeShouldThrowOnNullSessionId() { + verifyThrows(IllegalArgumentException.class, + () -> api.sessions().revoke(null), + "'session ID' cannot be null!"); + } + + @Test + public void shouldRevoke() throws Exception { + Request request = api.sessions().revoke("session_ID"); + assertThat(request, is(notNullValue())); + + server.noContentResponse(); + request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/sessions/session_ID/revoke")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + } + +} diff --git a/src/test/java/com/auth0/client/mgmt/SimpleTokenProviderTest.java b/src/test/java/com/auth0/client/mgmt/SimpleTokenProviderTest.java new file mode 100644 index 000000000..dc938fcdb --- /dev/null +++ b/src/test/java/com/auth0/client/mgmt/SimpleTokenProviderTest.java @@ -0,0 +1,32 @@ +package com.auth0.client.mgmt; + +import org.junit.jupiter.api.Test; + +import java.util.concurrent.CompletableFuture; + +import static com.auth0.AssertsUtil.verifyThrows; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +public class SimpleTokenProviderTest { + + @Test + public void throwsWhenTokenNull() { + verifyThrows(IllegalArgumentException.class, + () -> SimpleTokenProvider.create(null), + "'api token' cannot be null!"); + } + + @Test + public void getTokenReturnsToken() throws Exception { + TokenProvider provider = SimpleTokenProvider.create("token"); + assertThat(provider.getToken(), is("token")); + } + + @Test + public void getTokenAsyncReturnsTokenFuture() throws Exception { + TokenProvider provider = SimpleTokenProvider.create("token"); + CompletableFuture future = provider.getTokenAsync(); + assertThat(future.get(), is("token")); + } +} diff --git a/src/test/java/com/auth0/client/mgmt/StatsEntityTest.java b/src/test/java/com/auth0/client/mgmt/StatsEntityTest.java index c22e9ae1b..f67836904 100644 --- a/src/test/java/com/auth0/client/mgmt/StatsEntityTest.java +++ b/src/test/java/com/auth0/client/mgmt/StatsEntityTest.java @@ -1,18 +1,20 @@ package com.auth0.client.mgmt; -import com.auth0.json.mgmt.DailyStats; +import com.auth0.json.mgmt.stats.DailyStats; import com.auth0.net.Request; +import com.auth0.net.client.HttpMethod; import okhttp3.mockwebserver.RecordedRequest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.Calendar; import java.util.Date; import java.util.List; +import static com.auth0.AssertsUtil.verifyThrows; import static com.auth0.client.MockServer.*; import static com.auth0.client.RecordedRequestMatcher.*; -import static org.hamcrest.Matchers.*; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; public class StatsEntityTest extends BaseMgmtEntityTest { @@ -22,10 +24,10 @@ public void shouldGetActiveUsersCount() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_ACTIVE_USERS_COUNT, 200); - Integer response = request.execute(); + Integer response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/stats/active-users")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/stats/active-users")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -34,16 +36,17 @@ public void shouldGetActiveUsersCount() throws Exception { @Test public void shouldThrowOnGetDailyStatsWithNullDateFrom() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'date from' cannot be null!"); - api.stats().getDailyStats(null, new Date()); + verifyThrows(IllegalArgumentException.class, + () -> api.stats().getDailyStats(null, new Date()), + "'date from' cannot be null!"); + } @Test public void shouldThrowOnGetDailyStatsWithNullDateTo() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'date to' cannot be null!"); - api.stats().getDailyStats(new Date(), null); + verifyThrows(IllegalArgumentException.class, + () -> api.stats().getDailyStats(new Date(), null), + "'date to' cannot be null!"); } @SuppressWarnings("deprecation") @@ -60,10 +63,10 @@ public void shouldGetDailyStats() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_DAILY_STATS_LIST, 200); - List response = request.execute(); + List response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/stats/daily")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/stats/daily")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("from", "20161011")); @@ -78,7 +81,7 @@ public void shouldReturnEmptyDailyStats() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_EMPTY_LIST, 200); - List response = request.execute(); + List response = request.execute().getBody(); assertThat(response, is(notNullValue())); assertThat(response, is(emptyCollectionOf(DailyStats.class))); diff --git a/src/test/java/com/auth0/client/mgmt/TenantsEntityTest.java b/src/test/java/com/auth0/client/mgmt/TenantsEntityTest.java index e284580e0..5abe4e9c7 100644 --- a/src/test/java/com/auth0/client/mgmt/TenantsEntityTest.java +++ b/src/test/java/com/auth0/client/mgmt/TenantsEntityTest.java @@ -1,16 +1,25 @@ package com.auth0.client.mgmt; import com.auth0.client.mgmt.filter.FieldsFilter; +import com.auth0.json.mgmt.tenants.Clients; +import com.auth0.json.mgmt.tenants.DefaultTokenQuota; +import com.auth0.json.mgmt.tenants.Organizations; import com.auth0.json.mgmt.tenants.Tenant; +import com.auth0.json.mgmt.tokenquota.ClientCredentials; +import com.auth0.json.mgmt.tokenquota.TokenQuota; import com.auth0.net.Request; +import com.auth0.net.client.HttpMethod; import okhttp3.mockwebserver.RecordedRequest; -import org.junit.Test; +import org.junit.jupiter.api.Test; +import java.util.Map; + +import static com.auth0.AssertsUtil.verifyThrows; import static com.auth0.client.MockServer.MGMT_TENANT; +import static com.auth0.client.MockServer.*; import static com.auth0.client.RecordedRequestMatcher.*; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; public class TenantsEntityTest extends BaseMgmtEntityTest { @@ -20,10 +29,10 @@ public void shouldGetTenantSettings() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_TENANT, 200); - Tenant response = request.execute(); + Tenant response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/tenants/settings")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/tenants/settings")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -37,10 +46,10 @@ public void shouldGetTenantSettingsWithFields() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_TENANT, 200); - Tenant response = request.execute(); + Tenant response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/tenants/settings")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/tenants/settings")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("fields", "some,random,fields")); @@ -51,24 +60,57 @@ public void shouldGetTenantSettingsWithFields() throws Exception { @Test public void shouldThrowOnUpdateTenantSettingsWithNullData() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'tenant' cannot be null!"); - api.tenants().update(null); + verifyThrows(IllegalArgumentException.class, + () -> api.tenants().update(null), + "'tenant' cannot be null!"); } @Test public void shouldUpdateTenantSettings() throws Exception { - Request request = api.tenants().update(new Tenant()); + Tenant tenant = new Tenant(); + + DefaultTokenQuota defaultTokenQuota = new DefaultTokenQuota( + new Clients(new ClientCredentials(100, 20, true)), + new Organizations(new ClientCredentials(100, 20, true))); + + tenant.setDefaultTokenQuota(defaultTokenQuota); + Request request = api.tenants().update(tenant); assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_TENANT, 200); - Tenant response = request.execute(); + Tenant response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("PATCH", "/api/v2/tenants/settings")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PATCH, "/api/v2/tenants/settings")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + // Parse and validate the request body + Map body = bodyFromRequest(recordedRequest); + assertThat(body, is(notNullValue())); + + Map tokenQuotaMap = (Map) body.get("default_token_quota"); + assertThat(tokenQuotaMap, is(notNullValue())); + + // Validate "clients" nested structure + Map clientsMap = (Map) tokenQuotaMap.get("clients"); + assertThat(clientsMap, is(notNullValue())); + Map clientCredentialsMap = (Map) clientsMap.get("client_credentials"); + assertThat(clientCredentialsMap, is(notNullValue())); + assertThat(clientCredentialsMap, hasEntry("per_day", 100)); + assertThat(clientCredentialsMap, hasEntry("per_hour", 20)); + assertThat(clientCredentialsMap, hasEntry("enforce", true)); + + // Validate "organizations" nested structure + Map organizationsMap = (Map) tokenQuotaMap.get("organizations"); + assertThat(organizationsMap, is(notNullValue())); + Map organizationCredentialsMap = (Map) organizationsMap.get("client_credentials"); + assertThat(organizationCredentialsMap, is(notNullValue())); + assertThat(organizationCredentialsMap, hasEntry("per_day", 100)); + assertThat(organizationCredentialsMap, hasEntry("per_hour", 20)); + assertThat(organizationCredentialsMap, hasEntry("enforce", true)); + assertThat(response, is(notNullValue())); } } diff --git a/src/test/java/com/auth0/client/mgmt/TicketsEntityTest.java b/src/test/java/com/auth0/client/mgmt/TicketsEntityTest.java index 3e9da7a79..15a879655 100644 --- a/src/test/java/com/auth0/client/mgmt/TicketsEntityTest.java +++ b/src/test/java/com/auth0/client/mgmt/TicketsEntityTest.java @@ -3,24 +3,26 @@ import com.auth0.json.mgmt.tickets.EmailVerificationTicket; import com.auth0.json.mgmt.tickets.PasswordChangeTicket; import com.auth0.net.Request; +import com.auth0.net.client.HttpMethod; import okhttp3.mockwebserver.RecordedRequest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.Map; +import static com.auth0.AssertsUtil.verifyThrows; import static com.auth0.client.MockServer.*; import static com.auth0.client.RecordedRequestMatcher.hasHeader; import static com.auth0.client.RecordedRequestMatcher.hasMethodAndPath; -import static org.hamcrest.Matchers.*; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; public class TicketsEntityTest extends BaseMgmtEntityTest { @Test public void shouldThrowOnCreateEmailVerificationTicketWithNullData() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'email verification ticket' cannot be null!"); - api.tickets().requestEmailVerification(null); + verifyThrows(IllegalArgumentException.class, + () -> api.tickets().requestEmailVerification(null), + "'email verification ticket' cannot be null!"); } @Test @@ -33,10 +35,10 @@ public void shouldCreateEmailVerificationTicket() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_EMAIL_VERIFICATION_TICKET, 200); - EmailVerificationTicket response = request.execute(); + EmailVerificationTicket response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/api/v2/tickets/email-verification")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/tickets/email-verification")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -51,9 +53,9 @@ public void shouldCreateEmailVerificationTicket() throws Exception { @Test public void shouldThrowOnCreatePasswordChangeTicketWithNullData() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'password change ticket' cannot be null!"); - api.tickets().requestPasswordChange(null); + verifyThrows(IllegalArgumentException.class, + () -> api.tickets().requestPasswordChange(null), + "'password change ticket' cannot be null!"); } @Test @@ -62,10 +64,10 @@ public void shouldCreatePasswordChangeTicket() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_PASSWORD_CHANGE_TICKET, 200); - PasswordChangeTicket response = request.execute(); + PasswordChangeTicket response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/api/v2/tickets/password-change")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/tickets/password-change")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); diff --git a/src/test/java/com/auth0/client/mgmt/UserAttributeProfilesEntityTest.java b/src/test/java/com/auth0/client/mgmt/UserAttributeProfilesEntityTest.java new file mode 100644 index 000000000..0ef82f5ce --- /dev/null +++ b/src/test/java/com/auth0/client/mgmt/UserAttributeProfilesEntityTest.java @@ -0,0 +1,302 @@ +package com.auth0.client.mgmt; + +import com.auth0.client.MockServer; +import com.auth0.client.mgmt.filter.UserAttributeProfilesFilter; +import com.auth0.json.mgmt.userAttributeProfiles.*; +import com.auth0.net.Request; +import com.auth0.net.client.HttpMethod; +import okhttp3.mockwebserver.RecordedRequest; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import static com.auth0.AssertsUtil.verifyThrows; +import static com.auth0.client.MockServer.*; +import static com.auth0.client.RecordedRequestMatcher.*; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; + +public class UserAttributeProfilesEntityTest extends BaseMgmtEntityTest { + + // User Attribute Profiles entity tests + + @Test + public void shouldThrowOnGetUserAttributeProfileWithNullId() { + verifyThrows(IllegalArgumentException.class, + () -> api.userAttributeProfiles().get(null), + "'id' cannot be null!"); + } + + @Test + public void shouldGetUserAttributeProfile() throws Exception { + Request request = api.userAttributeProfiles().get("uap_1234567890"); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MockServer.MGMT_USER_ATTRIBUTE_PROFILE, 200); + UserAttributeProfile response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/user-attribute-profiles/uap_1234567890")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + assertThat(response, is(notNullValue())); + assertThat(response.getId(), is("uap_1234567890")); + assertThat(response.getName(), is("This is just a test")); + } + + @Test + public void shouldGetAllUserAttributeProfilesWithoutFilter() throws Exception { + Request request = api.userAttributeProfiles().getAll(null); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MockServer.MGMT_USER_ATTRIBUTE_PROFILES_LIST, 200); + UserAttributeProfilePage response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/user-attribute-profiles")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + assertThat(response, is(notNullValue())); + assertThat(response.getItems(), hasSize(3)); + } + + @Test + public void shouldGetAllUserAttributeProfilesWithFilter() throws Exception { + UserAttributeProfilesFilter filter = new UserAttributeProfilesFilter() + .withCheckpointPagination("uap_1234567890", 2); + + Request request = api.userAttributeProfiles().getAll(filter); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MockServer.MGMT_USER_ATTRIBUTE_PROFILES_LIST, 200); + UserAttributeProfilePage response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/user-attribute-profiles")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + assertThat(recordedRequest, hasQueryParameter("from", "uap_1234567890")); + assertThat(recordedRequest, hasQueryParameter("take", "2")); + + assertThat(response, is(notNullValue())); + assertThat(response.getItems(), hasSize(3)); + } + + @Test + public void shouldThrowOnUpdateUserAttributeProfileWithNullId() { + verifyThrows(IllegalArgumentException.class, + () -> api.userAttributeProfiles().update(null, new UserAttributeProfile()), + "'id' cannot be null!"); + } + + @Test + public void shouldThrowOnUpdateUserAttributeProfileWithNullProfile() { + verifyThrows(IllegalArgumentException.class, + () -> api.userAttributeProfiles().update("uap_1234567890", null), + "'userAttributeProfile' cannot be null!"); + } + + @Test + public void shouldUpdateUserAttributeProfile() throws Exception { + UserAttributeProfile profileToUpdate = new UserAttributeProfile(); + profileToUpdate.setName("This is just a test"); + + UserId userId = new UserId(); + userId.setOidcMapping("sub"); + userId.setSamlMapping(Arrays.asList("urn:oid:0.9.10.10.100.1.1")); // Replace List.of() with Arrays.asList() + userId.setScimMapping("userName"); + profileToUpdate.setUserId(userId); + + Map userAttributes = new HashMap<>(); + UserAttributes usernameAttr = new UserAttributes(); + usernameAttr.setLabel("test User"); + usernameAttr.setDescription("This is just a test"); + + OidcMapping oidcMapping = new OidcMapping(); + oidcMapping.setMapping("preferred_username"); + oidcMapping.setDisplayName("UserName"); + usernameAttr.setOidcMapping(oidcMapping); + + usernameAttr.setSamlMapping(Arrays.asList("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress")); // Replace List.of() with Arrays.asList() + usernameAttr.setScimMapping("displayName"); + usernameAttr.setAuth0Mapping("testUser"); + usernameAttr.setProfileRequired(false); + + StrategyOverridesUserAttributes strategyOverridesUserAttributes = new StrategyOverridesUserAttributes(); + strategyOverridesUserAttributes.setScimMapping("name.givenName"); + Map strategyOverridesMap = new HashMap<>(); + strategyOverridesMap.put("oidc", strategyOverridesUserAttributes); + usernameAttr.setStrategyOverrides(strategyOverridesMap); + + userAttributes.put("username", usernameAttr); + profileToUpdate.setUserAttributes(userAttributes); + + Request request = api.userAttributeProfiles().update("uap_1csqEmz4TE2P1o7izaATmb", profileToUpdate); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MockServer.MGMT_USER_ATTRIBUTE_PROFILE, 200); + UserAttributeProfile response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, + hasMethodAndPath(HttpMethod.PATCH, "/api/v2/user-attribute-profiles/uap_1csqEmz4TE2P1o7izaATmb")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + Map body = bodyFromRequest(recordedRequest); + assertThat(body, hasEntry("name", "This is just a test")); + assertThat(body, hasEntry(is("user_id"), is(notNullValue()))); + assertThat(body, hasEntry(is("user_attributes"), is(notNullValue()))); + + assertThat(response, is(notNullValue())); + } + + @Test + public void shouldThrowOnCreateUserAttributeProfileWithNullName() { + UserAttributeProfile profile = new UserAttributeProfile(); + profile.setName(null); + Map userAttributes = new HashMap<>(); + profile.setUserAttributes(userAttributes); + + verifyThrows(IllegalArgumentException.class, + () -> api.userAttributeProfiles().create(profile), + "'name' cannot be null!"); + } + + @Test + public void shouldThrowOnCreateUserAttributeProfileWithNullUserAttributes() { + UserAttributeProfile profile = new UserAttributeProfile(); + profile.setName("Test Profile"); + profile.setUserAttributes(null); + + verifyThrows(IllegalArgumentException.class, + () -> api.userAttributeProfiles().create(profile), + "'userAttributes' cannot be null!"); + } + + @Test + public void shouldCreateUserAttributeProfile() throws Exception { + UserAttributeProfile profileToCreate = new UserAttributeProfile(); + profileToCreate.setName("This is just a test"); + + UserId userId = new UserId(); + userId.setOidcMapping("sub"); + userId.setSamlMapping(Arrays.asList("urn:oid:0.9.10.10.100.1.1")); + userId.setScimMapping("userName"); + profileToCreate.setUserId(userId); + + Map userAttributes = new HashMap<>(); + UserAttributes usernameAttr = new UserAttributes(); + usernameAttr.setLabel("test User"); + usernameAttr.setDescription("This is just a test"); + + OidcMapping oidcMapping = new OidcMapping(); + oidcMapping.setMapping("preferred_username"); + oidcMapping.setDisplayName("UserName"); + usernameAttr.setOidcMapping(oidcMapping); + + usernameAttr.setSamlMapping(Arrays.asList("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress")); + usernameAttr.setScimMapping("displayName"); + usernameAttr.setAuth0Mapping("testUser"); + usernameAttr.setProfileRequired(false); + + StrategyOverridesUserAttributes strategyOverridesUserAttributes = new StrategyOverridesUserAttributes(); + strategyOverridesUserAttributes.setScimMapping("name.givenName"); + Map strategyOverridesMap = new HashMap<>(); + strategyOverridesMap.put("oidc", strategyOverridesUserAttributes); + usernameAttr.setStrategyOverrides(strategyOverridesMap); + + userAttributes.put("username", usernameAttr); + profileToCreate.setUserAttributes(userAttributes); + + Request request = api.userAttributeProfiles().create(profileToCreate); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MockServer.MGMT_USER_ATTRIBUTE_PROFILE, 201); + UserAttributeProfile response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/user-attribute-profiles")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + Map body = bodyFromRequest(recordedRequest); + assertThat(body, aMapWithSize(3)); + assertThat(body, hasEntry("name", "This is just a test")); + assertThat(body, hasEntry(is("user_id"), is(notNullValue()))); + assertThat(body, hasEntry(is("user_attributes"), is(notNullValue()))); + + assertThat(response, is(notNullValue())); + } + + @Test + public void shouldThrowOnDeleteUserAttributeProfileWithNullId() { + verifyThrows(IllegalArgumentException.class, + () -> api.userAttributeProfiles().delete(null), + "'id' cannot be null!"); + } + + @Test + public void shouldDeleteUserAttributeProfile() throws Exception { + Request request = api.userAttributeProfiles().delete("uap_1234567890"); + assertThat(request, is(notNullValue())); + + server.emptyResponse(204); + request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, + hasMethodAndPath(HttpMethod.DELETE, "/api/v2/user-attribute-profiles/uap_1234567890")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + } + + // User Attribute Profile Templates tests + + @Test + public void shouldThrowOnGetUserAttributeProfileTemplateWithNullId() { + verifyThrows(IllegalArgumentException.class, + () -> api.userAttributeProfiles().getTemplate(null), + "'id' cannot be null!"); + } + + @Test + public void shouldGetUserAttributeProfileTemplate() throws Exception { + Request request = api.userAttributeProfiles().getTemplate("auth0-generic"); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MockServer.MGMT_USER_ATTRIBUTE_PROFILE_TEMPLATE, 200); + UserAttributeProfileTemplate response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, + hasMethodAndPath(HttpMethod.GET, "/api/v2/user-attribute-profiles/templates/auth0-generic")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + assertThat(response, is(notNullValue())); + assertThat(response.getId(), is("auth0-generic")); + assertThat(response.getDisplayName(), is("A standard user attribute profile template")); + } + + @Test + public void shouldGetAllUserAttributeProfileTemplates() throws Exception { + Request request = api.userAttributeProfiles().getAllTemplates(); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MockServer.MGMT_USER_ATTRIBUTE_PROFILE_TEMPLATES_LIST, 200); + ListUserAttributeProfileTemplate response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/user-attribute-profiles/templates")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + assertThat(response, is(notNullValue())); + assertThat(response.getUserAttributeProfileTemplates(), hasSize(1)); + } +} diff --git a/src/test/java/com/auth0/client/mgmt/UserBlocksEntityTest.java b/src/test/java/com/auth0/client/mgmt/UserBlocksEntityTest.java index 1e3a967ba..37a73db52 100644 --- a/src/test/java/com/auth0/client/mgmt/UserBlocksEntityTest.java +++ b/src/test/java/com/auth0/client/mgmt/UserBlocksEntityTest.java @@ -2,22 +2,24 @@ import com.auth0.json.mgmt.userblocks.UserBlocks; import com.auth0.net.Request; +import com.auth0.net.client.HttpMethod; import okhttp3.mockwebserver.RecordedRequest; -import org.junit.Test; +import org.junit.jupiter.api.Test; +import static com.auth0.AssertsUtil.verifyThrows; import static com.auth0.client.MockServer.MGMT_USER_BLOCKS; import static com.auth0.client.RecordedRequestMatcher.*; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; -import static org.hamcrest.MatcherAssert.assertThat; public class UserBlocksEntityTest extends BaseMgmtEntityTest { @Test public void shouldThrowOnGetUserBlocksByIdentifierWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'identifier' cannot be null!"); - api.userBlocks().getByIdentifier(null); + verifyThrows(IllegalArgumentException.class, + () -> api.userBlocks().getByIdentifier(null), + "'identifier' cannot be null!"); } @Test @@ -26,10 +28,10 @@ public void shouldGetUserBlocksByIdentifier() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_USER_BLOCKS, 200); - UserBlocks response = request.execute(); + UserBlocks response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/user-blocks")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/user-blocks")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("identifier", "username")); @@ -39,9 +41,9 @@ public void shouldGetUserBlocksByIdentifier() throws Exception { @Test public void shouldThrowOnGetUserBlocksWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'user id' cannot be null!"); - api.userBlocks().get(null); + verifyThrows(IllegalArgumentException.class, + () -> api.userBlocks().get(null), + "'user id' cannot be null!"); } @Test @@ -50,10 +52,10 @@ public void shouldGetUserBlocks() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_USER_BLOCKS, 200); - UserBlocks response = request.execute(); + UserBlocks response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/user-blocks/1")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/user-blocks/1")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -62,9 +64,9 @@ public void shouldGetUserBlocks() throws Exception { @Test public void shouldThrowOnDeleteUserBlocksByIdentifierWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'identifier' cannot be null!"); - api.userBlocks().deleteByIdentifier(null); + verifyThrows(IllegalArgumentException.class, + () -> api.userBlocks().deleteByIdentifier(null), + "'identifier' cannot be null!"); } @Test @@ -73,10 +75,10 @@ public void shouldDeleteUserBlocksByIdentifier() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_USER_BLOCKS, 200); - request.execute(); + request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("DELETE", "/api/v2/user-blocks")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/user-blocks")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("identifier", "username")); @@ -84,9 +86,9 @@ public void shouldDeleteUserBlocksByIdentifier() throws Exception { @Test public void shouldThrowOnDeleteUserBlocksWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'user id' cannot be null!"); - api.userBlocks().delete(null); + verifyThrows(IllegalArgumentException.class, + () -> api.userBlocks().delete(null), + "'user id' cannot be null!"); } @Test @@ -95,10 +97,10 @@ public void shouldDeleteUserBlocks() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_USER_BLOCKS, 200); - request.execute(); + request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("DELETE", "/api/v2/user-blocks/1")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/user-blocks/1")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); } diff --git a/src/test/java/com/auth0/client/mgmt/UsersEntityTest.java b/src/test/java/com/auth0/client/mgmt/UsersEntityTest.java index 3bb3ec6f8..59da2b86f 100644 --- a/src/test/java/com/auth0/client/mgmt/UsersEntityTest.java +++ b/src/test/java/com/auth0/client/mgmt/UsersEntityTest.java @@ -4,26 +4,32 @@ import com.auth0.client.mgmt.filter.LogEventFilter; import com.auth0.client.mgmt.filter.PageFilter; import com.auth0.client.mgmt.filter.UserFilter; -import com.auth0.json.mgmt.Permission; -import com.auth0.json.mgmt.PermissionsPage; -import com.auth0.json.mgmt.RolesPage; import com.auth0.json.mgmt.guardian.Enrollment; import com.auth0.json.mgmt.logevents.LogEvent; import com.auth0.json.mgmt.logevents.LogEventsPage; import com.auth0.json.mgmt.organizations.OrganizationsPage; +import com.auth0.json.mgmt.permissions.Permission; +import com.auth0.json.mgmt.permissions.PermissionsPage; +import com.auth0.json.mgmt.roles.RolesPage; import com.auth0.json.mgmt.users.Identity; import com.auth0.json.mgmt.users.RecoveryCode; import com.auth0.json.mgmt.users.User; import com.auth0.json.mgmt.users.UsersPage; +import com.auth0.json.mgmt.users.authenticationmethods.AuthenticationMethod; +import com.auth0.json.mgmt.users.authenticationmethods.AuthenticationMethodsPage; +import com.auth0.json.mgmt.refreshtokens.RefreshTokensPage; +import com.auth0.json.mgmt.sessions.SessionsPage; import com.auth0.net.Request; +import com.auth0.net.client.HttpMethod; import okhttp3.mockwebserver.RecordedRequest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; +import static com.auth0.AssertsUtil.verifyThrows; import static com.auth0.client.MockServer.*; import static com.auth0.client.RecordedRequestMatcher.*; import static org.hamcrest.MatcherAssert.assertThat; @@ -37,10 +43,10 @@ public void shouldListUsersByEmail() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_USERS_LIST, 200); - List response = request.execute(); + List response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/users-by-email")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/users-by-email")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("email", "johndoe@auth0.com")); @@ -56,10 +62,10 @@ public void shouldListUsersByEmailWithFields() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_USERS_LIST, 200); - List response = request.execute(); + List response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/users-by-email")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/users-by-email")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("email", "johndoe@auth0.com")); @@ -76,7 +82,7 @@ public void shouldReturnEmptyUsersByEmail() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_EMPTY_LIST, 200); - List response = request.execute(); + List response = request.execute().getBody(); assertThat(response, is(notNullValue())); assertThat(response, is(emptyCollectionOf(User.class))); @@ -88,10 +94,10 @@ public void shouldListUsers() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_USERS_LIST, 200); - UsersPage response = request.execute(); + UsersPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/users")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/users")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -106,10 +112,10 @@ public void shouldListUsersWithPage() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_USERS_LIST, 200); - UsersPage response = request.execute(); + UsersPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/users")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/users")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("page", "23")); @@ -126,10 +132,10 @@ public void shouldListUsersWithTotals() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_USERS_PAGED_LIST, 200); - UsersPage response = request.execute(); + UsersPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/users")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/users")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("include_totals", "true")); @@ -149,10 +155,10 @@ public void shouldListUsersWithSort() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_USERS_LIST, 200); - UsersPage response = request.execute(); + UsersPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/users")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/users")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("sort", "date:1")); @@ -168,10 +174,10 @@ public void shouldListUsersWithQuery() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_USERS_LIST, 200); - UsersPage response = request.execute(); + UsersPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/users")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/users")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, not(hasQueryParameter("search_engine"))); @@ -188,10 +194,10 @@ public void shouldListUsersWithFields() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_USERS_LIST, 200); - UsersPage response = request.execute(); + UsersPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/users")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/users")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("fields", "some,random,fields")); @@ -207,7 +213,7 @@ public void shouldReturnEmptyUsers() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_EMPTY_LIST, 200); - UsersPage response = request.execute(); + UsersPage response = request.execute().getBody(); assertThat(response, is(notNullValue())); assertThat(response.getItems(), is(emptyCollectionOf(User.class))); @@ -215,9 +221,9 @@ public void shouldReturnEmptyUsers() throws Exception { @Test public void shouldThrowOnGetUserWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'user id' cannot be null!"); - api.users().get(null, null); + verifyThrows(IllegalArgumentException.class, + () -> api.users().get(null, null), + "'user id' cannot be null!"); } @Test @@ -226,10 +232,10 @@ public void shouldGetUser() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_USER, 200); - User response = request.execute(); + User response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/users/1")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/users/1")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -243,10 +249,10 @@ public void shouldGetUserWithFields() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_USER, 200); - User response = request.execute(); + User response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/users/1")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/users/1")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("fields", "some,random,fields")); @@ -257,9 +263,9 @@ public void shouldGetUserWithFields() throws Exception { @Test public void shouldThrowOnCreateUserWithNullData() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'user' cannot be null!"); - api.users().create(null); + verifyThrows(IllegalArgumentException.class, + () -> api.users().create(null), + "'user' cannot be null!"); } @Test @@ -268,10 +274,10 @@ public void shouldCreateUser() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_USER, 200); - User response = request.execute(); + User response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/api/v2/users")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/users")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -284,9 +290,9 @@ public void shouldCreateUser() throws Exception { @Test public void shouldThrowOnDeleteUserWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'user id' cannot be null!"); - api.users().delete(null); + verifyThrows(IllegalArgumentException.class, + () -> api.users().delete(null), + "'user id' cannot be null!"); } @Test @@ -295,26 +301,26 @@ public void shouldDeleteUser() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_USER, 200); - request.execute(); + request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("DELETE", "/api/v2/users/1")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/users/1")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); } @Test public void shouldThrowOnUpdateUserWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'user id' cannot be null!"); - api.users().update(null, new User("auth0")); + verifyThrows(IllegalArgumentException.class, + () -> api.users().update(null, new User("auth0")), + "'user id' cannot be null!"); } @Test public void shouldThrowOnUpdateUserWithNullData() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'user' cannot be null!"); - api.users().update("1", null); + verifyThrows(IllegalArgumentException.class, + () -> api.users().update("1", null), + "'user' cannot be null!"); } @Test @@ -323,10 +329,10 @@ public void shouldUpdateUser() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_USER, 200); - User response = request.execute(); + User response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("PATCH", "/api/v2/users/1")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PATCH, "/api/v2/users/1")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -340,9 +346,9 @@ public void shouldUpdateUser() throws Exception { @Test public void shouldThrowOnGetUserGuardianEnrollmentsWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'user id' cannot be null!"); - api.users().getEnrollments(null); + verifyThrows(IllegalArgumentException.class, + () -> api.users().getEnrollments(null), + "'user id' cannot be null!"); } @Test @@ -351,10 +357,10 @@ public void shouldGetUserGuardianEnrollments() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_GUARDIAN_ENROLLMENTS_LIST, 200); - List response = request.execute(); + List response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/users/1/enrollments")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/users/1/enrollments")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -367,7 +373,7 @@ public void shouldReturnEmptyUserGuardianEnrollments() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_EMPTY_LIST, 200); - List response = request.execute(); + List response = request.execute().getBody(); assertThat(response, is(notNullValue())); assertThat(response, is(emptyCollectionOf(Enrollment.class))); @@ -375,9 +381,9 @@ public void shouldReturnEmptyUserGuardianEnrollments() throws Exception { @Test public void shouldThrowOnGetUserLogEventsWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'user id' cannot be null!"); - api.users().getLogEvents(null, null); + verifyThrows(IllegalArgumentException.class, + () -> api.users().getLogEvents(null, null), + "'user id' cannot be null!"); } @Test @@ -386,10 +392,10 @@ public void shouldGetUserLogEvents() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_LOG_EVENTS_LIST, 200); - LogEventsPage response = request.execute(); + LogEventsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/users/1/logs")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/users/1/logs")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -403,10 +409,10 @@ public void shouldGetUserLogEventsWithQuery() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_LOG_EVENTS_LIST, 200); - LogEventsPage response = request.execute(); + LogEventsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/users/1/logs")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/users/1/logs")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("q", "date:[2022-03-13 TO *]")); @@ -422,10 +428,10 @@ public void shouldGetUserLogEventsWithPage() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_LOG_EVENTS_LIST, 200); - LogEventsPage response = request.execute(); + LogEventsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/users/1/logs")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/users/1/logs")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("page", "23")); @@ -442,10 +448,10 @@ public void shouldGetUserLogEventsWithTotals() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_LOG_EVENTS_PAGED_LIST, 200); - LogEventsPage response = request.execute(); + LogEventsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/users/1/logs")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/users/1/logs")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("include_totals", "true")); @@ -465,10 +471,10 @@ public void shouldGetUserLogEventsWithSort() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_LOG_EVENTS_LIST, 200); - LogEventsPage response = request.execute(); + LogEventsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/users/1/logs")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/users/1/logs")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("sort", "date:1")); @@ -484,10 +490,10 @@ public void shouldGetUserLogEventsWithFields() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_LOG_EVENTS_LIST, 200); - LogEventsPage response = request.execute(); + LogEventsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/users/1/logs")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/users/1/logs")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("fields", "some,random,fields")); @@ -503,24 +509,45 @@ public void shouldReturnEmptyUserLogEvents() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_EMPTY_LIST, 200); - LogEventsPage response = request.execute(); + LogEventsPage response = request.execute().getBody(); assertThat(response, is(notNullValue())); assertThat(response.getItems(), is(emptyCollectionOf(LogEvent.class))); } + @Test + public void shouldThrowOnDeleteUserAuthenticatorsWithNullId() { + verifyThrows(IllegalArgumentException.class, + () -> api.users().deleteAllAuthenticators(null), + "'user id' cannot be null!"); + } + + @Test + public void shouldDeleteUserAuthenticators() throws Exception { + Request request = api.users().deleteAllAuthenticators("auth0|23"); + assertThat(request, is(notNullValue())); + + server.emptyResponse(204); + request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/users/auth0%7C23/authenticators")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + } + @Test public void shouldThrowOnDeleteUserMultifactorProviderWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'user id' cannot be null!"); - api.users().deleteMultifactorProvider(null, "duo"); + verifyThrows(IllegalArgumentException.class, + () -> api.users().deleteMultifactorProvider(null, "duo"), + "'user id' cannot be null!"); } @Test public void shouldThrowOnDeleteUserMultifactorProviderWithNullProvider() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'provider' cannot be null!"); - api.users().deleteMultifactorProvider("1", null); + verifyThrows(IllegalArgumentException.class, + () -> api.users().deleteMultifactorProvider("1", null), + "'provider' cannot be null!"); } @Test @@ -529,19 +556,19 @@ public void shouldDeleteUserMultifactorProvider() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_EMAIL_PROVIDER, 200); - request.execute(); + request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("DELETE", "/api/v2/users/1/multifactor/duo")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/users/1/multifactor/duo")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); } @Test public void shouldThrowOnRotateUserRecoveryCodeWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'user id' cannot be null!"); - api.users().rotateRecoveryCode(null); + verifyThrows(IllegalArgumentException.class, + () -> api.users().rotateRecoveryCode(null), + "'user id' cannot be null!"); } @Test @@ -550,10 +577,10 @@ public void shouldRotateUserRecoveryCode() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_RECOVERY_CODE, 200); - RecoveryCode response = request.execute(); + RecoveryCode response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/api/v2/users/1/recovery-code-regeneration")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/users/1/recovery-code-regeneration")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -562,37 +589,37 @@ public void shouldRotateUserRecoveryCode() throws Exception { @Test public void shouldThrowOnLinkUserIdentityWithNullPrimaryId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'primary user id' cannot be null!"); - api.users().linkIdentity(null, "2", "auth0", null); + verifyThrows(IllegalArgumentException.class, + () -> api.users().linkIdentity(null, "2", "auth0", null), + "'primary user id' cannot be null!"); } @Test public void shouldThrowOnLinkUserIdentityWithNullSecondaryId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'secondary user id' cannot be null!"); - api.users().linkIdentity("1", null, "auth0", null); + verifyThrows(IllegalArgumentException.class, + () -> api.users().linkIdentity("1", null, "auth0", null), + "'secondary user id' cannot be null!"); } @Test public void shouldThrowOnLinkUserIdentityWithNullSecondaryToken() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'secondary id token' cannot be null!"); - api.users().linkIdentity("1", null); + verifyThrows(IllegalArgumentException.class, + () -> api.users().linkIdentity("1", null), + "'secondary id token' cannot be null!"); } @Test public void shouldThrowOnLinkUserIdentityWithNullUserId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'primary user id' cannot be null!"); - api.users().linkIdentity(null, "2"); + verifyThrows(IllegalArgumentException.class, + () -> api.users().linkIdentity(null, "2"), + "'primary user id' cannot be null!"); } @Test public void shouldThrowOnLinkUserIdentityWithNullProvider() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'provider' cannot be null!"); - api.users().linkIdentity("1", "2", null, null); + verifyThrows(IllegalArgumentException.class, + () -> api.users().linkIdentity("1", "2", null, null), + "'provider' cannot be null!"); } @Test @@ -601,10 +628,10 @@ public void shouldLinkUserIdentity() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_IDENTITIES_LIST, 200); - List response = request.execute(); + List response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/api/v2/users/1/identities")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/users/1/identities")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -622,10 +649,10 @@ public void shouldLinkUserIdentityBySecondaryIdToken() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_IDENTITIES_LIST, 200); - List response = request.execute(); + List response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/api/v2/users/1/identities")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/users/1/identities")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -642,10 +669,10 @@ public void shouldLinkUserIdentityWithConnectionId() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_IDENTITIES_LIST, 200); - List response = request.execute(); + List response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/api/v2/users/1/identities")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/users/1/identities")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -660,23 +687,23 @@ public void shouldLinkUserIdentityWithConnectionId() throws Exception { @Test public void shouldThrowOnUnlinkUserIdentityWithNullPrimaryId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'primary user id' cannot be null!"); - api.users().unlinkIdentity(null, "2", "auth0"); + verifyThrows(IllegalArgumentException.class, + () -> api.users().unlinkIdentity(null, "2", "auth0"), + "'primary user id' cannot be null!"); } @Test public void shouldThrowOnUnlinkUserIdentityWithNullSecondaryId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'secondary user id' cannot be null!"); - api.users().unlinkIdentity("1", null, "auth0"); + verifyThrows(IllegalArgumentException.class, + () -> api.users().unlinkIdentity("1", null, "auth0"), + "'secondary user id' cannot be null!"); } @Test public void shouldThrowOnUnlinkUserIdentityWithNullProvider() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'provider' cannot be null!"); - api.users().unlinkIdentity("1", "2", null); + verifyThrows(IllegalArgumentException.class, + () -> api.users().unlinkIdentity("1", "2", null), + "'provider' cannot be null!"); } @Test @@ -685,10 +712,10 @@ public void shouldUnlinkUserIdentity() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_IDENTITIES_LIST, 200); - List response = request.execute(); + List response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("DELETE", "/api/v2/users/1/identities/auth0/2")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/users/1/identities/auth0/2")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -697,9 +724,9 @@ public void shouldUnlinkUserIdentity() throws Exception { @Test public void shouldThrowOnListRolesWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'user id' cannot be null!"); - api.users().listRoles(null, null); + verifyThrows(IllegalArgumentException.class, + () -> api.users().listRoles(null, null), + "'user id' cannot be null!"); } @Test @@ -708,10 +735,10 @@ public void shouldListRolesWithoutFilter() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_USER_ROLES_PAGED_LIST, 200); - RolesPage response = request.execute(); + RolesPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/users/1/roles")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/users/1/roles")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -726,10 +753,10 @@ public void shouldListRolesWithPage() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_USER_ROLES_PAGED_LIST, 200); - RolesPage response = request.execute(); + RolesPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/users/1/roles")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/users/1/roles")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("page", "23")); @@ -746,10 +773,10 @@ public void shouldListRolesWithTotals() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_USER_ROLES_PAGED_LIST, 200); - RolesPage response = request.execute(); + RolesPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/users/1/roles")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/users/1/roles")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("include_totals", "true")); @@ -764,23 +791,23 @@ public void shouldListRolesWithTotals() throws Exception { @Test public void shouldThrowOnAddRolesWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'user id' cannot be null!"); - api.users().addRoles(null, Collections.emptyList()); + verifyThrows(IllegalArgumentException.class, + () -> api.users().addRoles(null, Collections.emptyList()), + "'user id' cannot be null!"); } @Test public void shouldThrowOnAddRolesWithNullList() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'role ids' cannot be null!"); - api.users().addRoles("1", null); + verifyThrows(IllegalArgumentException.class, + () -> api.users().addRoles("1", null), + "'role ids' cannot be null!"); } @Test public void shouldThrowOnAddRolesWithEmptyList() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'role ids' cannot be empty!"); - api.users().addRoles("1", Collections.emptyList()); + verifyThrows(IllegalArgumentException.class, + () -> api.users().addRoles("1", Collections.emptyList()), + "'role ids' cannot be empty!"); } @Test @@ -789,10 +816,10 @@ public void shouldAddRoles() throws Exception { assertThat(request, is(notNullValue())); server.emptyResponse(200); - Object response = request.execute(); + Object response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/api/v2/users/1/roles")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/users/1/roles")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -805,23 +832,23 @@ public void shouldAddRoles() throws Exception { @Test public void shouldThrowOnRemoveRolesWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'user id' cannot be null!"); - api.users().removeRoles(null, Collections.emptyList()); + verifyThrows(IllegalArgumentException.class, + () -> api.users().removeRoles(null, Collections.emptyList()), + "'user id' cannot be null!"); } @Test public void shouldThrowOnRemoveRolesWithNullList() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'role ids' cannot be null!"); - api.users().removeRoles("1", null); + verifyThrows(IllegalArgumentException.class, + () -> api.users().removeRoles("1", null), + "'role ids' cannot be null!"); } @Test public void shouldThrowOnRemoveRolesWithEmptyList() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'role ids' cannot be empty!"); - api.users().removeRoles("1", Collections.emptyList()); + verifyThrows(IllegalArgumentException.class, + () -> api.users().removeRoles("1", Collections.emptyList()), + "'role ids' cannot be empty!"); } @Test @@ -830,10 +857,10 @@ public void shouldRemoveRoles() throws Exception { assertThat(request, is(notNullValue())); server.emptyResponse( 200); - Object response = request.execute(); + Object response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("DELETE", "/api/v2/users/1/roles")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/users/1/roles")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -850,10 +877,10 @@ public void shouldListPermissionsWithoutFilter() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_USER_PERMISSIONS_PAGED_LIST, 200); - PermissionsPage response = request.execute(); + PermissionsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/users/1/permissions")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/users/1/permissions")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -868,10 +895,10 @@ public void shouldListPermissionsWithPage() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_USER_PERMISSIONS_PAGED_LIST, 200); - PermissionsPage response = request.execute(); + PermissionsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/users/1/permissions")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/users/1/permissions")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("page", "23")); @@ -888,10 +915,10 @@ public void shouldListPermissionsWithTotal() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(MGMT_USER_PERMISSIONS_PAGED_LIST, 200); - PermissionsPage response = request.execute(); + PermissionsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/users/1/permissions")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/users/1/permissions")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("include_totals", "true")); @@ -906,23 +933,23 @@ public void shouldListPermissionsWithTotal() throws Exception { @Test public void shouldThrowOnAddPermissionsWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'user id' cannot be null!"); - api.users().addPermissions(null, Collections.emptyList()); + verifyThrows(IllegalArgumentException.class, + () -> api.users().addPermissions(null, Collections.emptyList()), + "'user id' cannot be null!"); } @Test public void shouldThrowOnAddPermissionsWithNullList() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'permissions' cannot be null!"); - api.users().addPermissions("1", null); + verifyThrows(IllegalArgumentException.class, + () -> api.users().addPermissions("1", null), + "'permissions' cannot be null!"); } @Test public void shouldThrowOnAddPermissionsWithEmptyList() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'permissions' cannot be empty!"); - api.users().addPermissions("1", Collections.emptyList()); + verifyThrows(IllegalArgumentException.class, + () -> api.users().addPermissions("1", Collections.emptyList()), + "'permissions' cannot be empty!"); } @Test @@ -935,10 +962,10 @@ public void shouldAddPermissions() throws Exception { assertThat(request, is(notNullValue())); server.emptyResponse(200); - Object response = request.execute(); + Object response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("POST", "/api/v2/users/1/permissions")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/users/1/permissions")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -951,23 +978,23 @@ public void shouldAddPermissions() throws Exception { @Test public void shouldThrowOnRemovePermissionsWithNullId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'user id' cannot be null!"); - api.users().removePermissions(null, Collections.emptyList()); + verifyThrows(IllegalArgumentException.class, + () -> api.users().removePermissions(null, Collections.emptyList()), + "'user id' cannot be null!"); } @Test public void shouldThrowOnRemovePermissionsWithNullList() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'permissions' cannot be null!"); - api.users().removePermissions("roleId", null); + verifyThrows(IllegalArgumentException.class, + () -> api.users().removePermissions("roleId", null), + "'permissions' cannot be null!"); } @Test public void shouldThrowOnRemovePermissionsWithEmptyList() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'permissions' cannot be empty!"); - api.users().removePermissions("roleId", Collections.emptyList()); + verifyThrows(IllegalArgumentException.class, + () -> api.users().removePermissions("roleId", Collections.emptyList()), + "'permissions' cannot be empty!"); } @Test @@ -980,10 +1007,10 @@ public void shouldRemovePermissions() throws Exception { assertThat(request, is(notNullValue())); server.emptyResponse(200); - Object response = request.execute(); + Object response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("DELETE", "/api/v2/users/1/permissions")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/users/1/permissions")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -996,9 +1023,9 @@ public void shouldRemovePermissions() throws Exception { @Test public void shouldThrowOnGetOrganizationsWithNullUserId() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("user ID"); - api.users().getOrganizations(null, null); + verifyThrows(IllegalArgumentException.class, + () -> api.users().getOrganizations(null, null), + "'user ID' cannot be null!"); } @Test @@ -1007,10 +1034,10 @@ public void shouldGetUserOrganizationsWithoutFilter() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(ORGANIZATIONS_LIST, 200); - OrganizationsPage response = request.execute(); + OrganizationsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/users/1/organizations")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/users/1/organizations")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); @@ -1024,10 +1051,10 @@ public void shouldGetUserOrganizationsWithPaging() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(ORGANIZATIONS_LIST, 200); - OrganizationsPage response = request.execute(); + OrganizationsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/users/1/organizations")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/users/1/organizations")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("page", "0")); @@ -1043,10 +1070,10 @@ public void shouldGetUserOrganizationsWithTotals() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(ORGANIZATIONS_PAGED_LIST, 200); - OrganizationsPage response = request.execute(); + OrganizationsPage response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest, hasMethodAndPath("GET", "/api/v2/users/1/organizations")); + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/users/1/organizations")); assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); assertThat(recordedRequest, hasQueryParameter("include_totals", "true")); @@ -1057,4 +1084,424 @@ public void shouldGetUserOrganizationsWithTotals() throws Exception { assertThat(response.getTotal(), is(2)); assertThat(response.getLimit(), is(20)); } + + @Test + public void shouldGetUserAuthenticationMethodsWithNullId() { + verifyThrows(IllegalArgumentException.class, + () -> api.users().getAuthenticationMethods(null, null), + "'user ID' cannot be null!"); + } + + @Test + public void shouldGetUserAuthenticationMethodsWithoutFilter() throws Exception { + Request request = api.users().getAuthenticationMethods("1", null); + assertThat(request, is(notNullValue())); + + server.jsonResponse(AUTHENTICATOR_METHOD_LIST, 200); + AuthenticationMethodsPage response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/users/1/authentication-methods")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + assertThat(response, is(notNullValue())); + } + + + + @Test + public void shouldGetUserAuthenticationMethodsWithPaging() throws Exception { + Request request = api.users().getAuthenticationMethods("1", + new PageFilter().withPage(0, 20)); + assertThat(request, is(notNullValue())); + + server.jsonResponse(AUTHENTICATOR_METHOD_PAGED_LIST, 200); + AuthenticationMethodsPage response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/users/1/authentication-methods")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + assertThat(recordedRequest, hasQueryParameter("page", "0")); + assertThat(recordedRequest, hasQueryParameter("per_page", "20")); + + assertThat(response, is(notNullValue())); + } + + @Test + public void shouldGetUserAuthenticationMethodsWithTotals() throws Exception { + Request request = api.users().getAuthenticationMethods("1", + new PageFilter().withTotals(true)); + assertThat(request, is(notNullValue())); + + server.jsonResponse(AUTHENTICATOR_METHOD_PAGED_LIST, 200); + AuthenticationMethodsPage response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/users/1/authentication-methods")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + assertThat(recordedRequest, hasQueryParameter("include_totals", "true")); + + assertThat(response, is(notNullValue())); + assertThat(response.getItems(), hasSize(1)); + assertThat(response.getStart(), is(0)); + assertThat(response.getTotal(), is(3)); + assertThat(response.getLimit(), is(1)); + } + + @Test + public void shouldUpdateUserAuthenticationMethodsWithNullId() { + verifyThrows(IllegalArgumentException.class, + () -> api.users().updateAuthenticationMethods(null, new ArrayList<>()), + "'user ID' cannot be null!"); + } + + @Test + public void shouldUpdateUserAuthenticationMethodsWithAuthenticatorMethodsNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.users().updateAuthenticationMethods("1", null), + "'authentication methods' cannot be null!"); + } + + @Test + public void shouldUpdateUserAuthenticationMethods() throws Exception { + ArrayList list = new ArrayList<>(); + AuthenticationMethod authenticationMethod = new AuthenticationMethod(); + list.add(authenticationMethod); + Request> request = api.users().updateAuthenticationMethods("1", list); + assertThat(request, is(notNullValue())); + + server.jsonResponse(AUTHENTICATOR_METHOD_UPDATE, 200); + List response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PUT, "/api/v2/users/1/authentication-methods")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + assertThat(response, is(notNullValue())); + + } + + @Test + public void shouldNotCreateUserAuthenticationMethodsWithNullId() { + verifyThrows(IllegalArgumentException.class, + () -> api.users().createAuthenticationMethods(null, new AuthenticationMethod()), + "'user ID' cannot be null!"); + } + + @Test + public void shouldNotCreateUserAuthenticationMethodsWithAuthenticatorMethodsNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.users().createAuthenticationMethods("1", null), + "'authentication methods' cannot be null!"); + } + + @Test + public void shouldCreateUserAuthenticationMethods() throws Exception { + AuthenticationMethod authenticationMethod = new AuthenticationMethod(); + Request request = api.users().createAuthenticationMethods("1", authenticationMethod); + assertThat(request, is(notNullValue())); + + server.jsonResponse(AUTHENTICATOR_METHOD_CREATE, 200); + AuthenticationMethod response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/users/1/authentication-methods")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + assertThat(response, is(notNullValue())); + } + + @Test + public void shouldNotGetUserAuthenticationMethodsByIdWithNullId() { + verifyThrows(IllegalArgumentException.class, + () -> api.users().getAuthenticationMethodById(null, "1"), + "'user ID' cannot be null!"); + } + + @Test + public void shouldNotGetUserAuthenticationMethodsByIdWithAuthenticatorMethodIdNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.users().getAuthenticationMethodById("1", null), + "'authentication method ID' cannot be null!"); + } + + @Test + public void shouldGetUserAuthenticationMethodById() throws Exception { + Request request = api.users().getAuthenticationMethodById("1", "1"); + assertThat(request, is(notNullValue())); + + server.jsonResponse(AUTHENTICATOR_METHOD_BY_ID, 200); + AuthenticationMethod response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/users/1/authentication-methods/1")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + assertThat(response, is(notNullValue())); + } + + @Test + public void shouldNotUpdateUserAuthenticationMethodsByIdWithNullId() { + verifyThrows(IllegalArgumentException.class, + () -> api.users().updateAuthenticationMethodById(null, "1", new AuthenticationMethod()), + "'user ID' cannot be null!"); + } + + @Test + public void shouldNotUpdateUserAuthenticationMethodsByIdWithAuthenticatorMethodIdNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.users().updateAuthenticationMethodById("1", null, new AuthenticationMethod()), + "'authentication method ID' cannot be null!"); + } + + @Test + public void shouldNotUpdateUserAuthenticationMethodsByIdWithAuthenticatorMethodNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.users().updateAuthenticationMethodById("1", "1", null), + "'authentication method' cannot be null!"); + } + + @Test + public void shouldUpdateUserAuthenticationMethodById() throws Exception { + Request request = api.users().updateAuthenticationMethodById("1", "1", new AuthenticationMethod()); + assertThat(request, is(notNullValue())); + + server.jsonResponse(AUTHENTICATOR_METHOD_UPDATE_BY_ID, 200); + AuthenticationMethod response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.PATCH, "/api/v2/users/1/authentication-methods/1")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + assertThat(response, is(notNullValue())); + } + + @Test + public void shouldNotDeleteUserAuthenticationMethodsByIdWithNullId() { + verifyThrows(IllegalArgumentException.class, + () -> api.users().deleteAuthenticationMethodById(null, "1"), + "'user ID' cannot be null!"); + } + + @Test + public void shouldNotDeleteUserAuthenticationMethodsByIdWithAuthenticatorMethodIdNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.users().deleteAuthenticationMethodById("1", null), + "'authentication method ID' cannot be null!"); + } + + @Test + public void shouldDeleteUserAuthenticationMethodById() throws Exception { + Request request = api.users().deleteAuthenticationMethodById("1", "1"); + assertThat(request, is(notNullValue())); + + server.noContentResponse(); + request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/users/1/authentication-methods/1")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + } + + @Test + public void shouldNotDeleteAllAuthenticationMethodsWithNullUserId() { + verifyThrows(IllegalArgumentException.class, + () -> api.users().deleteAllAuthenticationMethods(null), + "'user ID' cannot be null!"); + } + + @Test + public void shouldDeleteAllAuthenticationMethods() throws Exception { + Request request = api.users().deleteAllAuthenticationMethods("1"); + assertThat(request, is(notNullValue())); + + server.noContentResponse(); + request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/users/1/authentication-methods")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + } + + @Test + public void invalidateRememberedBrowsersThrowsWhenUserIdIsNull() { + verifyThrows(IllegalArgumentException.class, + () -> api.users().invalidateRememberedBrowsers(null), + "'user ID' cannot be null!"); + } + + @Test + public void shouldInvalidateRememberedBrowsers() throws Exception { + Request request = api.users().invalidateRememberedBrowsers("userId"); + assertThat(request, is(notNullValue())); + + server.noContentResponse(); + Void response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.POST, "/api/v2/users/userId/multifactor/actions/invalidate-remember-browser")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + } + + @Test + public void shouldListRefreshTokensWithoutFilter() throws Exception { + Request request = api.users().listRefreshTokens("1", null); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_USER_REFRESH_TOKENS, 200); + RefreshTokensPage response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/users/1/refresh-tokens")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + assertThat(response, is(notNullValue())); + assertThat(response.getTokens(), hasSize(2)); + } + + @Test + public void shouldListRefreshTokensWithPage() throws Exception { + PageFilter filter = new PageFilter().withFrom("tokenId2").withTake(5); + Request request = api.users().listRefreshTokens("1", filter); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_USER_REFRESH_TOKENS, 200); + RefreshTokensPage response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/users/1/refresh-tokens")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + assertThat(recordedRequest, hasQueryParameter("from", "tokenId2")); + assertThat(recordedRequest, hasQueryParameter("take", "5")); + + assertThat(response, is(notNullValue())); + assertThat(response.getTokens(), hasSize(2)); + } + + @Test + public void shouldListRefreshTokensWithTotal() throws Exception { + PageFilter filter = new PageFilter().withTotals(true); + Request request = api.users().listRefreshTokens("1", filter); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_USER_REFRESH_TOKENS, 200); + RefreshTokensPage response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/users/1/refresh-tokens")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + assertThat(recordedRequest, hasQueryParameter("include_totals", "true")); + + assertThat(response, is(notNullValue())); + assertThat(response.getTokens(), hasSize(2)); + assertThat(response.getTotal(), is(11)); + } + + @Test + public void shouldNotDeleteRefreshTokensWithNullUserId() { + verifyThrows(IllegalArgumentException.class, + () -> api.users().deleteRefreshTokens(null), + "'user ID' cannot be null!"); + } + + @Test + public void shouldDeleteRefreshTokens() throws Exception { + Request request = api.users().deleteRefreshTokens("1"); + assertThat(request, is(notNullValue())); + + server.noContentResponse(); + request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/users/1/refresh-tokens")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + } + + @Test + public void shouldListSessionsWithoutFilter() throws Exception { + Request request = api.users().listSessions("1", null); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_USER_SESSIONS, 200); + SessionsPage response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/users/1/sessions")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + + assertThat(response, is(notNullValue())); + assertThat(response.getSessions(), hasSize(1)); + } + + @Test + public void shouldListSessionsWithPage() throws Exception { + PageFilter filter = new PageFilter().withFrom("sessionId3").withTake(9); + Request request = api.users().listSessions("1", filter); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_USER_SESSIONS, 200); + SessionsPage response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/users/1/sessions")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + assertThat(recordedRequest, hasQueryParameter("from", "sessionId3")); + assertThat(recordedRequest, hasQueryParameter("take", "9")); + + assertThat(response, is(notNullValue())); + assertThat(response.getSessions(), hasSize(1)); + } + + @Test + public void shouldListSessionsWithTotal() throws Exception { + PageFilter filter = new PageFilter().withTotals(true); + Request request = api.users().listSessions("1", filter); + assertThat(request, is(notNullValue())); + + server.jsonResponse(MGMT_USER_SESSIONS, 200); + SessionsPage response = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.GET, "/api/v2/users/1/sessions")); + assertThat(recordedRequest, hasHeader("Content-Type", "application/json")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + assertThat(recordedRequest, hasQueryParameter("include_totals", "true")); + + assertThat(response, is(notNullValue())); + assertThat(response.getSessions(), hasSize(1)); + assertThat(response.getTotal(), is(9)); + } + + @Test + public void shouldNotDeleteSessionsWithNullUserId() { + verifyThrows(IllegalArgumentException.class, + () -> api.users().deleteRefreshTokens(null), + "'user ID' cannot be null!"); + } + + @Test + public void shouldDeleteSessions() throws Exception { + Request request = api.users().deleteSessions("1"); + assertThat(request, is(notNullValue())); + + server.noContentResponse(); + request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest, hasMethodAndPath(HttpMethod.DELETE, "/api/v2/users/1/sessions")); + assertThat(recordedRequest, hasHeader("Authorization", "Bearer apiToken")); + } } diff --git a/src/test/java/com/auth0/client/mgmt/filter/ActionsFilterTest.java b/src/test/java/com/auth0/client/mgmt/filter/ActionsFilterTest.java index 9baa5863c..a6e20c10d 100644 --- a/src/test/java/com/auth0/client/mgmt/filter/ActionsFilterTest.java +++ b/src/test/java/com/auth0/client/mgmt/filter/ActionsFilterTest.java @@ -1,6 +1,6 @@ package com.auth0.client.mgmt.filter; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.Map; diff --git a/src/test/java/com/auth0/client/mgmt/filter/ClientGrantsFilterTest.java b/src/test/java/com/auth0/client/mgmt/filter/ClientGrantsFilterTest.java index 4dd071481..b7b4f9b8c 100644 --- a/src/test/java/com/auth0/client/mgmt/filter/ClientGrantsFilterTest.java +++ b/src/test/java/com/auth0/client/mgmt/filter/ClientGrantsFilterTest.java @@ -1,8 +1,8 @@ package com.auth0.client.mgmt.filter; import org.hamcrest.Matchers; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; @@ -12,7 +12,7 @@ public class ClientGrantsFilterTest { private ClientGrantsFilter filter; - @Before + @BeforeEach public void setUp() { filter = new ClientGrantsFilter(); } diff --git a/src/test/java/com/auth0/client/mgmt/filter/ConnectionFilterTest.java b/src/test/java/com/auth0/client/mgmt/filter/ConnectionFilterTest.java index 37ab26947..16961428b 100644 --- a/src/test/java/com/auth0/client/mgmt/filter/ConnectionFilterTest.java +++ b/src/test/java/com/auth0/client/mgmt/filter/ConnectionFilterTest.java @@ -1,8 +1,8 @@ package com.auth0.client.mgmt.filter; import org.hamcrest.Matchers; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; @@ -12,7 +12,7 @@ public class ConnectionFilterTest { private ConnectionFilter filter; - @Before + @BeforeEach public void setUp() { filter = new ConnectionFilter(); } diff --git a/src/test/java/com/auth0/client/mgmt/filter/DeviceCredentialsFilterTest.java b/src/test/java/com/auth0/client/mgmt/filter/DeviceCredentialsFilterTest.java index b034fed54..95632f324 100644 --- a/src/test/java/com/auth0/client/mgmt/filter/DeviceCredentialsFilterTest.java +++ b/src/test/java/com/auth0/client/mgmt/filter/DeviceCredentialsFilterTest.java @@ -1,8 +1,8 @@ package com.auth0.client.mgmt.filter; import org.hamcrest.Matchers; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; @@ -12,7 +12,7 @@ public class DeviceCredentialsFilterTest { private DeviceCredentialsFilter filter; - @Before + @BeforeEach public void setUp() { filter = new DeviceCredentialsFilter(); } @@ -63,4 +63,23 @@ public void shouldFilterWithoutFields() { assertThat(filter.getAsMap(), Matchers.hasEntry("fields", "a,b,c")); assertThat(filter.getAsMap(), Matchers.hasEntry("include_fields", false)); } + + @Test + public void shouldFilterWithPage() { + DeviceCredentialsFilter instance = filter.withPage(1, 10); + + assertThat(filter, is(instance)); + assertThat(filter.getAsMap(), is(notNullValue())); + assertThat(filter.getAsMap(), Matchers.hasEntry("page", 1)); + assertThat(filter.getAsMap(), Matchers.hasEntry("per_page", 10)); + } + + @Test + public void shouldFilterWithTotals() { + DeviceCredentialsFilter instance = filter.withTotals(true); + + assertThat(filter, is(instance)); + assertThat(filter.getAsMap(), is(notNullValue())); + assertThat(filter.getAsMap(), Matchers.hasEntry("include_totals", true)); + } } diff --git a/src/test/java/com/auth0/client/mgmt/filter/FieldFilterTest.java b/src/test/java/com/auth0/client/mgmt/filter/FieldFilterTest.java index 038730407..6b9b66b36 100644 --- a/src/test/java/com/auth0/client/mgmt/filter/FieldFilterTest.java +++ b/src/test/java/com/auth0/client/mgmt/filter/FieldFilterTest.java @@ -1,8 +1,8 @@ package com.auth0.client.mgmt.filter; import org.hamcrest.Matchers; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; @@ -12,7 +12,7 @@ public class FieldFilterTest { private FieldsFilter filter; - @Before + @BeforeEach public void setUp() { filter = new FieldsFilter(); } diff --git a/src/test/java/com/auth0/client/mgmt/filter/GrantsFilterTest.java b/src/test/java/com/auth0/client/mgmt/filter/GrantsFilterTest.java index 271cef3c8..3f9176c68 100644 --- a/src/test/java/com/auth0/client/mgmt/filter/GrantsFilterTest.java +++ b/src/test/java/com/auth0/client/mgmt/filter/GrantsFilterTest.java @@ -1,8 +1,8 @@ package com.auth0.client.mgmt.filter; import org.hamcrest.Matchers; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; @@ -12,7 +12,7 @@ public class GrantsFilterTest { private GrantsFilter filter; - @Before + @BeforeEach public void setUp() { filter = new GrantsFilter(); } diff --git a/src/test/java/com/auth0/client/mgmt/filter/LogEventFilterTest.java b/src/test/java/com/auth0/client/mgmt/filter/LogEventFilterTest.java index f3df3deb6..43abb25da 100644 --- a/src/test/java/com/auth0/client/mgmt/filter/LogEventFilterTest.java +++ b/src/test/java/com/auth0/client/mgmt/filter/LogEventFilterTest.java @@ -1,8 +1,8 @@ package com.auth0.client.mgmt.filter; import org.hamcrest.Matchers; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; @@ -12,7 +12,7 @@ public class LogEventFilterTest { private LogEventFilter filter; - @Before + @BeforeEach public void setUp() { filter = new LogEventFilter(); } diff --git a/src/test/java/com/auth0/client/mgmt/filter/PageBasedPaginationFilterTest.java b/src/test/java/com/auth0/client/mgmt/filter/PageBasedPaginationFilterTest.java new file mode 100644 index 000000000..282cfc69a --- /dev/null +++ b/src/test/java/com/auth0/client/mgmt/filter/PageBasedPaginationFilterTest.java @@ -0,0 +1,39 @@ +package com.auth0.client.mgmt.filter; + +import org.hamcrest.Matchers; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.MatcherAssert.assertThat; + +public class PageBasedPaginationFilterTest { + + private PageBasedPaginationFilter filter; + + @BeforeEach + public void setUp() { + filter = new PageBasedPaginationFilter(); + } + + @Test + public void shouldFilterByPage() { + PageBasedPaginationFilter instance = filter.withPage(5, 10); + + assertThat(filter, is(instance)); + assertThat(filter.getAsMap(), is(notNullValue())); + assertThat(filter.getAsMap(), Matchers.hasEntry("per_page", 10)); + assertThat(filter.getAsMap(), Matchers.hasEntry("page", 5)); + } + + @Test + public void shouldIncludeTotals() { + PageBasedPaginationFilter instance = filter.withTotals(true); + + assertThat(filter, is(instance)); + assertThat(filter.getAsMap(), is(notNullValue())); + assertThat(filter.getAsMap(), Matchers.hasEntry("include_totals", true)); + } + +} diff --git a/src/test/java/com/auth0/client/mgmt/filter/PageFilterTest.java b/src/test/java/com/auth0/client/mgmt/filter/PageFilterTest.java index 8a67ff85b..99c297d24 100644 --- a/src/test/java/com/auth0/client/mgmt/filter/PageFilterTest.java +++ b/src/test/java/com/auth0/client/mgmt/filter/PageFilterTest.java @@ -1,8 +1,8 @@ package com.auth0.client.mgmt.filter; import org.hamcrest.Matchers; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; @@ -12,7 +12,7 @@ public class PageFilterTest { private PageFilter filter; - @Before + @BeforeEach public void setUp() { filter = new PageFilter(); } diff --git a/src/test/java/com/auth0/client/mgmt/filter/QueryFilterTest.java b/src/test/java/com/auth0/client/mgmt/filter/QueryFilterTest.java index a62ad2f8c..662a8aabd 100644 --- a/src/test/java/com/auth0/client/mgmt/filter/QueryFilterTest.java +++ b/src/test/java/com/auth0/client/mgmt/filter/QueryFilterTest.java @@ -1,30 +1,22 @@ package com.auth0.client.mgmt.filter; import org.hamcrest.Matchers; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.Matchers.isA; +import java.io.UnsupportedEncodingException; + +import static com.auth0.AssertsUtil.verifyThrows; +import static org.hamcrest.CoreMatchers.*; import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.spy; -import java.io.UnsupportedEncodingException; - -import org.junit.Rule; -import org.junit.rules.ExpectedException; - public class QueryFilterTest { - @SuppressWarnings("deprecation") - @Rule - public ExpectedException exception = ExpectedException.none(); - private QueryFilter filter; - @Before + @BeforeEach public void setUp() { filter = new QueryFilter(); } @@ -88,13 +80,14 @@ public void shouldFilterWithoutFields() { @Test public void shouldThrowIllegalStateExceptionWhenUtf8IsNotSupported() throws Exception { - exception.expect(IllegalStateException.class); - exception.expectMessage("UTF-8 encoding not supported by current Java platform implementation."); - exception.expectCause(isA(UnsupportedEncodingException.class)); String value = "my test value"; QueryFilter filter = spy(new QueryFilter()); doThrow(UnsupportedEncodingException.class).when(filter).urlEncode(value); - filter.withQuery(value); + + IllegalStateException e = verifyThrows(IllegalStateException.class, + () -> filter.withQuery(value), + "UTF-8 encoding not supported by current Java platform implementation."); + assertThat(e.getCause(), instanceOf(UnsupportedEncodingException.class)); } } diff --git a/src/test/java/com/auth0/client/mgmt/filter/ResourceServersFilterTest.java b/src/test/java/com/auth0/client/mgmt/filter/ResourceServersFilterTest.java index 6339a2161..a7af3a927 100644 --- a/src/test/java/com/auth0/client/mgmt/filter/ResourceServersFilterTest.java +++ b/src/test/java/com/auth0/client/mgmt/filter/ResourceServersFilterTest.java @@ -1,8 +1,8 @@ package com.auth0.client.mgmt.filter; import org.hamcrest.Matchers; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; @@ -12,7 +12,7 @@ public class ResourceServersFilterTest { private ResourceServersFilter filter; - @Before + @BeforeEach public void setUp() { filter = new ResourceServersFilter(); } diff --git a/src/test/java/com/auth0/client/mgmt/filter/RoleFilterTest.java b/src/test/java/com/auth0/client/mgmt/filter/RoleFilterTest.java index e9b2491e2..09039a755 100644 --- a/src/test/java/com/auth0/client/mgmt/filter/RoleFilterTest.java +++ b/src/test/java/com/auth0/client/mgmt/filter/RoleFilterTest.java @@ -1,18 +1,18 @@ package com.auth0.client.mgmt.filter; +import org.hamcrest.Matchers; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.MatcherAssert.assertThat; -import org.hamcrest.Matchers; -import org.junit.Before; -import org.junit.Test; - public class RoleFilterTest { private RolesFilter filter; - @Before + @BeforeEach public void setUp() { filter = new RolesFilter(); } diff --git a/src/test/java/com/auth0/client/mgmt/filter/RulesFilterTest.java b/src/test/java/com/auth0/client/mgmt/filter/RulesFilterTest.java index ded4b41b7..84fa0009d 100644 --- a/src/test/java/com/auth0/client/mgmt/filter/RulesFilterTest.java +++ b/src/test/java/com/auth0/client/mgmt/filter/RulesFilterTest.java @@ -1,8 +1,8 @@ package com.auth0.client.mgmt.filter; import org.hamcrest.Matchers; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; @@ -12,7 +12,7 @@ public class RulesFilterTest { private RulesFilter filter; - @Before + @BeforeEach public void setUp() { filter = new RulesFilter(); } diff --git a/src/test/java/com/auth0/client/mgmt/filter/UserFilterTest.java b/src/test/java/com/auth0/client/mgmt/filter/UserFilterTest.java index bfba9bfcc..57e7977d9 100644 --- a/src/test/java/com/auth0/client/mgmt/filter/UserFilterTest.java +++ b/src/test/java/com/auth0/client/mgmt/filter/UserFilterTest.java @@ -1,8 +1,8 @@ package com.auth0.client.mgmt.filter; import org.hamcrest.Matchers; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import static org.hamcrest.CoreMatchers.*; import static org.hamcrest.MatcherAssert.assertThat; @@ -11,7 +11,7 @@ public class UserFilterTest { private UserFilter filter; - @Before + @BeforeEach public void setUp() { filter = new UserFilter(); } @@ -87,4 +87,13 @@ public void shouldFilterWithoutFields() { assertThat(filter.getAsMap(), Matchers.hasEntry("fields", "a,b,c")); assertThat(filter.getAsMap(), Matchers.hasEntry("include_fields", false)); } + + @Test + public void shouldFilterWithConnection() { + UserFilter instance = filter.withConnection("test"); + + assertThat(filter, is(instance)); + assertThat(filter.getAsMap(), is(notNullValue())); + assertThat(filter.getAsMap(), Matchers.hasEntry("connection", "test")); + } } diff --git a/src/test/java/com/auth0/client/mgmt/filter/UsersExportFilterTest.java b/src/test/java/com/auth0/client/mgmt/filter/UsersExportFilterTest.java index 99401c7a2..b5379f1a2 100644 --- a/src/test/java/com/auth0/client/mgmt/filter/UsersExportFilterTest.java +++ b/src/test/java/com/auth0/client/mgmt/filter/UsersExportFilterTest.java @@ -2,22 +2,22 @@ import com.auth0.json.mgmt.jobs.UsersExportField; import org.hamcrest.Matchers; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import java.util.ArrayList; import java.util.List; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.core.IsNull.nullValue; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.IsNull.nullValue; public class UsersExportFilterTest { private UsersExportFilter filter; - @Before + @BeforeEach public void setUp() { filter = new UsersExportFilter(); } @@ -64,4 +64,12 @@ public void shouldFilterByFields() { assertThat(bodyFields.get(2).getExportAs(), is("custom")); } + @Test + public void shouldFilterByConnectionId() { + UsersExportFilter instance = filter.withConnectionId("123"); + + assertThat(filter, is(instance)); + assertThat(filter.getAsMap(), is(notNullValue())); + assertThat(filter.getAsMap(), Matchers.hasEntry("connection_id", "123")); + } } diff --git a/src/test/java/com/auth0/client/mgmt/filter/UsersImportOptionsTest.java b/src/test/java/com/auth0/client/mgmt/filter/UsersImportOptionsTest.java index 612ea9542..11590d29c 100644 --- a/src/test/java/com/auth0/client/mgmt/filter/UsersImportOptionsTest.java +++ b/src/test/java/com/auth0/client/mgmt/filter/UsersImportOptionsTest.java @@ -1,8 +1,8 @@ package com.auth0.client.mgmt.filter; import org.hamcrest.Matchers; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; @@ -11,7 +11,7 @@ public class UsersImportOptionsTest { private UsersImportOptions options; - @Before + @BeforeEach public void setUp() { options = new UsersImportOptions(); } @@ -42,4 +42,13 @@ public void shouldSetUpsert() { assertThat(options.getAsMap(), is(notNullValue())); assertThat(options.getAsMap(), Matchers.hasEntry("upsert", true)); } + + @Test + public void shouldSetConnectionId() { + UsersImportOptions instance = options.withConnectionId("123"); + + assertThat(options, is(instance)); + assertThat(options.getAsMap(), is(notNullValue())); + assertThat(options.getAsMap(), Matchers.hasEntry("connection_id", "123")); + } } diff --git a/src/test/java/com/auth0/exception/APIExceptionTest.java b/src/test/java/com/auth0/exception/APIExceptionTest.java index 1b0240b59..90f79ceff 100644 --- a/src/test/java/com/auth0/exception/APIExceptionTest.java +++ b/src/test/java/com/auth0/exception/APIExceptionTest.java @@ -1,7 +1,7 @@ package com.auth0.exception; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import java.util.Collections; import java.util.HashMap; @@ -18,7 +18,7 @@ public class APIExceptionTest { private final static int ERROR_CODE = 42; private final static String EXPECTED_ERROR_MESSAGE_PREFIX = "Request failed with status code " + ERROR_CODE + ": "; - @Before + @BeforeEach public void setUp() { values = new HashMap<>(); } diff --git a/src/test/java/com/auth0/json/JsonMatcher.java b/src/test/java/com/auth0/json/JsonMatcher.java index 2066c6679..7a7b622b7 100644 --- a/src/test/java/com/auth0/json/JsonMatcher.java +++ b/src/test/java/com/auth0/json/JsonMatcher.java @@ -38,7 +38,7 @@ protected boolean matchesSafely(String item, Description mismatchDescription) { return false; } if (!item.contains(getStringKey(key))) { - mismatchDescription.appendText("JSON didn't contained the key ").appendValue(key); + mismatchDescription.appendText("JSON does not contain the key ").appendValue(key); return false; } } diff --git a/src/test/java/com/auth0/json/JsonTest.java b/src/test/java/com/auth0/json/JsonTest.java index 3fee0262a..1555021ed 100644 --- a/src/test/java/com/auth0/json/JsonTest.java +++ b/src/test/java/com/auth0/json/JsonTest.java @@ -1,17 +1,15 @@ package com.auth0.json; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.util.StdDateFormat; + import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.text.ParseException; -import java.text.SimpleDateFormat; import java.util.Date; -import java.util.TimeZone; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.util.StdDateFormat; public class JsonTest { diff --git a/src/test/java/com/auth0/json/ObjectMapperProviderTest.java b/src/test/java/com/auth0/json/ObjectMapperProviderTest.java new file mode 100644 index 000000000..d0e3216cc --- /dev/null +++ b/src/test/java/com/auth0/json/ObjectMapperProviderTest.java @@ -0,0 +1,16 @@ +package com.auth0.json; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; + +public class ObjectMapperProviderTest { + + @Test + public void providesSameInstance() { + ObjectMapper mapper = ObjectMapperProvider.getMapper(); + assertThat(mapper, equalTo(ObjectMapperProvider.getMapper())); + } +} diff --git a/src/test/java/com/auth0/json/auth/CreatedUserTest.java b/src/test/java/com/auth0/json/auth/CreatedUserTest.java index 43c7f2192..802a9dc7e 100644 --- a/src/test/java/com/auth0/json/auth/CreatedUserTest.java +++ b/src/test/java/com/auth0/json/auth/CreatedUserTest.java @@ -1,7 +1,7 @@ package com.auth0.json.auth; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; @@ -61,4 +61,4 @@ public void shouldDeserializeCustomExternalConnectionUser() throws Exception { assertThat(user.isEmailVerified(), is(true)); assertThat(user.getUserId(), is("from|user_id")); } -} \ No newline at end of file +} diff --git a/src/test/java/com/auth0/json/auth/PasswordlessEmailResponseTest.java b/src/test/java/com/auth0/json/auth/PasswordlessEmailResponseTest.java index 04b6136d0..420eca6ac 100644 --- a/src/test/java/com/auth0/json/auth/PasswordlessEmailResponseTest.java +++ b/src/test/java/com/auth0/json/auth/PasswordlessEmailResponseTest.java @@ -1,7 +1,7 @@ package com.auth0.json.auth; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; diff --git a/src/test/java/com/auth0/json/auth/PasswordlessSmsResponseTest.java b/src/test/java/com/auth0/json/auth/PasswordlessSmsResponseTest.java index ab2ffef36..312995f81 100644 --- a/src/test/java/com/auth0/json/auth/PasswordlessSmsResponseTest.java +++ b/src/test/java/com/auth0/json/auth/PasswordlessSmsResponseTest.java @@ -1,12 +1,10 @@ package com.auth0.json.auth; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.notNullValue; -import static org.hamcrest.Matchers.nullValue; +import static org.hamcrest.Matchers.*; public class PasswordlessSmsResponseTest extends JsonTest { diff --git a/src/test/java/com/auth0/json/auth/TokenHolderTest.java b/src/test/java/com/auth0/json/auth/TokenHolderTest.java index 5b20dc996..4547f342b 100644 --- a/src/test/java/com/auth0/json/auth/TokenHolderTest.java +++ b/src/test/java/com/auth0/json/auth/TokenHolderTest.java @@ -1,7 +1,7 @@ package com.auth0.json.auth; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.time.Instant; import java.util.Date; diff --git a/src/test/java/com/auth0/json/auth/UserInfoTest.java b/src/test/java/com/auth0/json/auth/UserInfoTest.java index bf5063cf7..c3cc6ab12 100644 --- a/src/test/java/com/auth0/json/auth/UserInfoTest.java +++ b/src/test/java/com/auth0/json/auth/UserInfoTest.java @@ -3,7 +3,7 @@ import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; import org.hamcrest.collection.IsMapContaining; -import org.junit.Test; +import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; diff --git a/src/test/java/com/auth0/json/mgmt/ClientGrantTest.java b/src/test/java/com/auth0/json/mgmt/ClientGrantTest.java index b935461de..cade1f906 100644 --- a/src/test/java/com/auth0/json/mgmt/ClientGrantTest.java +++ b/src/test/java/com/auth0/json/mgmt/ClientGrantTest.java @@ -2,7 +2,8 @@ import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; -import org.junit.Test; +import com.auth0.json.mgmt.clientgrants.ClientGrant; +import org.junit.jupiter.api.Test; import java.util.Arrays; @@ -11,7 +12,7 @@ public class ClientGrantTest extends JsonTest { - private static final String json = "{\"client_id\":\"clientId\",\"audience\":\"aud\",\"scope\":[\"one\",\"two\"]}"; + private static final String json = "{\"client_id\":\"clientId\",\"audience\":\"aud\",\"scope\":[\"one\",\"two\"],\"organization_usage\": \"allow\",\"allow_any_organization\":true}"; private static final String readOnlyJson = "{\"id\":\"grantId\"}"; @Test @@ -20,12 +21,16 @@ public void shouldSerialize() throws Exception { grant.setAudience("aud"); grant.setClientId("clientId"); grant.setScope(Arrays.asList("one", "two")); + grant.setOrganizationUsage("require"); + grant.setAllowAnyOrganization(true); String serialized = toJSON(grant); assertThat(serialized, is(notNullValue())); assertThat(serialized, JsonMatcher.hasEntry("client_id", "clientId")); assertThat(serialized, JsonMatcher.hasEntry("audience", "aud")); assertThat(serialized, JsonMatcher.hasEntry("scope", Arrays.asList("one", "two"))); + assertThat(serialized, JsonMatcher.hasEntry("organization_usage", "require")); + assertThat(serialized, JsonMatcher.hasEntry("allow_any_organization", true)); } @Test @@ -37,6 +42,8 @@ public void shouldDeserialize() throws Exception { assertThat(grant.getAudience(), is("aud")); assertThat(grant.getClientId(), is("clientId")); assertThat(grant.getScope(), contains("one", "two")); + assertThat(grant.getOrganizationUsage(), is("allow")); + assertThat(grant.getAllowAnyOrganization(), is(true)); } @Test @@ -46,4 +53,4 @@ public void shouldIncludeReadOnlyValuesOnDeserialize() throws Exception { assertThat(grant.getId(), is("grantId")); } -} \ No newline at end of file +} diff --git a/src/test/java/com/auth0/json/mgmt/DailyStatsTest.java b/src/test/java/com/auth0/json/mgmt/DailyStatsTest.java index 74c4c1fe4..25f9cdf19 100644 --- a/src/test/java/com/auth0/json/mgmt/DailyStatsTest.java +++ b/src/test/java/com/auth0/json/mgmt/DailyStatsTest.java @@ -1,12 +1,11 @@ package com.auth0.json.mgmt; import com.auth0.json.JsonTest; -import org.junit.Test; +import com.auth0.json.mgmt.stats.DailyStats; +import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.*; public class DailyStatsTest extends JsonTest { private static final String json = "{\"logins\":123,\"date\":\"2017-01-18T17:45:08.328Z\"}"; @@ -20,4 +19,4 @@ public void shouldDeserialize() throws Exception { assertThat(stats.getLogins(), is(123)); } -} \ No newline at end of file +} diff --git a/src/test/java/com/auth0/json/mgmt/DeviceCredentialsTest.java b/src/test/java/com/auth0/json/mgmt/DeviceCredentialsTest.java index d244e0f94..46c85956b 100644 --- a/src/test/java/com/auth0/json/mgmt/DeviceCredentialsTest.java +++ b/src/test/java/com/auth0/json/mgmt/DeviceCredentialsTest.java @@ -2,7 +2,8 @@ import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; -import org.junit.Test; +import com.auth0.json.mgmt.devicecredentials.DeviceCredentials; +import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; @@ -47,4 +48,4 @@ public void shouldIncludeReadOnlyValuesOnDeserialize() throws Exception { assertThat(credentials.getId(), is("credentialsId")); } -} \ No newline at end of file +} diff --git a/src/test/java/com/auth0/json/mgmt/EmailTemplateTest.java b/src/test/java/com/auth0/json/mgmt/EmailTemplateTest.java index 617ce68ff..01a8addf1 100644 --- a/src/test/java/com/auth0/json/mgmt/EmailTemplateTest.java +++ b/src/test/java/com/auth0/json/mgmt/EmailTemplateTest.java @@ -2,7 +2,8 @@ import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; -import org.junit.Test; +import com.auth0.json.mgmt.emailtemplates.EmailTemplate; +import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; @@ -54,4 +55,4 @@ public void shouldHaveDefaults() { EmailTemplate template = new EmailTemplate(); assertThat(template.getSyntax(), is("liquid")); } -} \ No newline at end of file +} diff --git a/src/test/java/com/auth0/json/mgmt/GrantTest.java b/src/test/java/com/auth0/json/mgmt/GrantTest.java index 42817912c..8f7c27e2e 100644 --- a/src/test/java/com/auth0/json/mgmt/GrantTest.java +++ b/src/test/java/com/auth0/json/mgmt/GrantTest.java @@ -2,7 +2,8 @@ import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; -import org.junit.Test; +import com.auth0.json.mgmt.grants.Grant; +import org.junit.jupiter.api.Test; import java.util.Arrays; @@ -48,4 +49,4 @@ public void shouldIncludeReadOnlyValuesOnDeserialize() throws Exception { assertThat(grant.getId(), is("grantId")); } -} \ No newline at end of file +} diff --git a/src/test/java/com/auth0/json/mgmt/ResourceServerTest.java b/src/test/java/com/auth0/json/mgmt/ResourceServerTest.java index e54a53129..a5e6bd04b 100644 --- a/src/test/java/com/auth0/json/mgmt/ResourceServerTest.java +++ b/src/test/java/com/auth0/json/mgmt/ResourceServerTest.java @@ -1,15 +1,19 @@ package com.auth0.json.mgmt; +import com.auth0.json.JsonMatcher; +import com.auth0.json.JsonTest; +import com.auth0.json.mgmt.resourceserver.*; +import org.junit.jupiter.api.Test; + import java.util.ArrayList; +import java.util.Arrays; import java.util.List; - -import com.auth0.json.JsonTest; -import org.junit.Test; +import java.util.stream.Collectors; import static com.auth0.json.JsonMatcher.hasEntry; -import static org.hamcrest.Matchers.hasSize; -import static org.hamcrest.Matchers.is; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.containsString; public class ResourceServerTest extends JsonTest { private final static String RESOURCE_SERVER_JSON = "src/test/resources/mgmt/resource_server.json"; @@ -30,6 +34,18 @@ public void deserialize() throws Exception { assertThat(deserialized.getTokenDialect(), is("access_token")); assertThat(deserialized.getTokenLifetime(), is(86400)); assertThat(deserialized.getVerificationLocation(), is("verification_location")); + assertThat(deserialized.getConsentPolicy(), is("transactional-authorization-with-mfa")); + assertThat(deserialized.getAuthorizationDetails(), is(notNullValue())); + assertThat(deserialized.getAuthorizationDetails().size(), is(2)); + assertThat(deserialized.getAuthorizationDetails().stream().map(AuthorizationDetails::getType).collect(Collectors.toList()), containsInAnyOrder("payment", "my custom type")); + assertThat(deserialized.getTokenEncryption(), notNullValue()); + assertThat(deserialized.getTokenEncryption().getFormat(), is("compact-nested-jwe")); + assertThat(deserialized.getTokenEncryption().getEncryptionKey().getAlg(), is("RSA-OAEP-256")); + assertThat(deserialized.getTokenEncryption().getEncryptionKey().getKid(), is("my kid")); + assertThat(deserialized.getTokenEncryption().getEncryptionKey().getName(), is("my JWE public key")); + assertThat(deserialized.getTokenEncryption().getEncryptionKey().getThumbprintSha256(), is("thumbprint")); + assertThat(deserialized.getProofOfPossession().getMechanism(), is("mtls")); + assertThat(deserialized.getProofOfPossession().getRequired(), is(true)); } @Test @@ -54,9 +70,24 @@ public void serialize() throws Exception { entity.setTokenLifetime(86400); entity.setTokenDialect("access_token_authz"); entity.setVerificationLocation("verification_location"); + entity.setConsentPolicy("transactional-authorization-with-mfa"); + AuthorizationDetails authorizationDetails1 = new AuthorizationDetails("type1"); + AuthorizationDetails authorizationDetails2 = new AuthorizationDetails("type2"); + entity.setAuthorizationDetails(Arrays.asList(authorizationDetails1, authorizationDetails2)); + EncryptionKey encryptionKey = new EncryptionKey(); + encryptionKey.setName("name"); + encryptionKey.setAlg("alg"); + encryptionKey.setKid("kid"); + encryptionKey.setPem("pem"); + TokenEncryption tokenEncryption = new TokenEncryption("format", encryptionKey); + entity.setTokenEncryption(tokenEncryption); + ProofOfPossession proofOfPossession = new ProofOfPossession("mtls", true); + entity.setProofOfPossession(proofOfPossession); String json = toJSON(entity); + System.out.println(json); + assertThat(json, hasEntry("id", "23445566abab")); assertThat(json, hasEntry("name", "Some API")); assertThat(json, hasEntry("identifier", "https://api.my-company.com/api/v2/")); @@ -68,5 +99,9 @@ public void serialize() throws Exception { assertThat(json, hasEntry("token_lifetime", 86400)); assertThat(json, hasEntry("token_dialect", "access_token_authz")); assertThat(json, hasEntry("verification_location", "verification_location")); + assertThat(json, hasEntry("consent_policy", "transactional-authorization-with-mfa")); + assertThat(json, hasEntry("authorization_details", notNullValue())); + assertThat(json, hasEntry("token_encryption", containsString("{\"format\":\"format\",\"encryption_key\":{\"name\":\"name\",\"alg\":\"alg\",\"pem\":\"pem\",\"kid\":\"kid\"}}"))); + assertThat(json, hasEntry("proof_of_possession", containsString("{\"mechanism\":\"mtls\",\"required\":true}"))); } -} \ No newline at end of file +} diff --git a/src/test/java/com/auth0/json/mgmt/RoleTest.java b/src/test/java/com/auth0/json/mgmt/RoleTest.java index 257c278fa..3b9bf5c05 100644 --- a/src/test/java/com/auth0/json/mgmt/RoleTest.java +++ b/src/test/java/com/auth0/json/mgmt/RoleTest.java @@ -1,13 +1,14 @@ package com.auth0.json.mgmt; +import com.auth0.json.JsonMatcher; +import com.auth0.json.JsonTest; +import com.auth0.json.mgmt.roles.Role; +import org.junit.jupiter.api.Test; + import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; -import com.auth0.json.JsonMatcher; -import com.auth0.json.JsonTest; -import org.junit.Test; - public class RoleTest extends JsonTest { private static final String json = "{\"name\":\"role\",\"description\":\"desc\"}"; diff --git a/src/test/java/com/auth0/json/mgmt/RuleTest.java b/src/test/java/com/auth0/json/mgmt/RuleTest.java index 4fe70f693..fc8eebec0 100644 --- a/src/test/java/com/auth0/json/mgmt/RuleTest.java +++ b/src/test/java/com/auth0/json/mgmt/RuleTest.java @@ -2,7 +2,8 @@ import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; -import org.junit.Test; +import com.auth0.json.mgmt.rules.Rule; +import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; @@ -46,4 +47,4 @@ public void shouldIncludeReadOnlyValuesOnDeserialize() throws Exception { assertThat(rule.getId(), is("ruleId")); assertThat(rule.getStage(), is("login_success")); } -} \ No newline at end of file +} diff --git a/src/test/java/com/auth0/json/mgmt/RulesConfigTest.java b/src/test/java/com/auth0/json/mgmt/RulesConfigTest.java index 0bee33e6f..f352ab9e2 100644 --- a/src/test/java/com/auth0/json/mgmt/RulesConfigTest.java +++ b/src/test/java/com/auth0/json/mgmt/RulesConfigTest.java @@ -2,7 +2,8 @@ import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; -import org.junit.Test; +import com.auth0.json.mgmt.rules.RulesConfig; +import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; @@ -37,4 +38,4 @@ public void shouldIncludeReadOnlyValuesOnDeserialize() throws Exception { assertThat(rule.getKey(), is("my-key")); } -} \ No newline at end of file +} diff --git a/src/test/java/com/auth0/json/mgmt/ScopeTest.java b/src/test/java/com/auth0/json/mgmt/ScopeTest.java index f1f6848a4..d5415d7a7 100644 --- a/src/test/java/com/auth0/json/mgmt/ScopeTest.java +++ b/src/test/java/com/auth0/json/mgmt/ScopeTest.java @@ -2,10 +2,11 @@ import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; -import org.junit.Test; +import com.auth0.json.mgmt.resourceserver.Scope; +import org.junit.jupiter.api.Test; -import static org.hamcrest.Matchers.is; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; public class ScopeTest extends JsonTest { private static final String SCOPE_JSON = "src/test/resources/mgmt/scope.json"; @@ -27,4 +28,4 @@ public void deserialize() throws Exception { assertThat(deserialized.getValue(), is("read:client_grants")); assertThat(deserialized.getDescription(), is("Read Client Grants")); } -} \ No newline at end of file +} diff --git a/src/test/java/com/auth0/json/mgmt/TokenTest.java b/src/test/java/com/auth0/json/mgmt/TokenTest.java index d30983b4a..20d877728 100644 --- a/src/test/java/com/auth0/json/mgmt/TokenTest.java +++ b/src/test/java/com/auth0/json/mgmt/TokenTest.java @@ -2,7 +2,8 @@ import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; -import org.junit.Test; +import com.auth0.json.mgmt.blacklists.Token; +import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; @@ -31,4 +32,4 @@ public void shouldDeserialize() throws Exception { assertThat(token.getJTI(), is("id")); } -} \ No newline at end of file +} diff --git a/src/test/java/com/auth0/json/mgmt/actions/ActionTest.java b/src/test/java/com/auth0/json/mgmt/actions/ActionTest.java index cd3b28093..929535dd5 100644 --- a/src/test/java/com/auth0/json/mgmt/actions/ActionTest.java +++ b/src/test/java/com/auth0/json/mgmt/actions/ActionTest.java @@ -2,13 +2,14 @@ import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.Arrays; import java.util.Collections; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; public class ActionTest extends JsonTest { diff --git a/src/test/java/com/auth0/json/mgmt/actions/ActionsPageTest.java b/src/test/java/com/auth0/json/mgmt/actions/ActionsPageTest.java index 2d02da0a2..e8fba5252 100644 --- a/src/test/java/com/auth0/json/mgmt/actions/ActionsPageTest.java +++ b/src/test/java/com/auth0/json/mgmt/actions/ActionsPageTest.java @@ -1,7 +1,7 @@ package com.auth0.json.mgmt.actions; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.Collections; diff --git a/src/test/java/com/auth0/json/mgmt/actions/BindingsPageTest.java b/src/test/java/com/auth0/json/mgmt/actions/BindingsPageTest.java index a91f696f8..248cc7476 100644 --- a/src/test/java/com/auth0/json/mgmt/actions/BindingsPageTest.java +++ b/src/test/java/com/auth0/json/mgmt/actions/BindingsPageTest.java @@ -1,7 +1,7 @@ package com.auth0.json.mgmt.actions; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.Collections; diff --git a/src/test/java/com/auth0/json/mgmt/actions/BindingsUpdateRequestTest.java b/src/test/java/com/auth0/json/mgmt/actions/BindingsUpdateRequestTest.java index a239367ac..cd91257d3 100644 --- a/src/test/java/com/auth0/json/mgmt/actions/BindingsUpdateRequestTest.java +++ b/src/test/java/com/auth0/json/mgmt/actions/BindingsUpdateRequestTest.java @@ -1,7 +1,7 @@ package com.auth0.json.mgmt.actions; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; diff --git a/src/test/java/com/auth0/json/mgmt/actions/ExecutionTest.java b/src/test/java/com/auth0/json/mgmt/actions/ExecutionTest.java index 3420daa32..7cd8ce291 100644 --- a/src/test/java/com/auth0/json/mgmt/actions/ExecutionTest.java +++ b/src/test/java/com/auth0/json/mgmt/actions/ExecutionTest.java @@ -1,7 +1,7 @@ package com.auth0.json.mgmt.actions; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.List; diff --git a/src/test/java/com/auth0/json/mgmt/actions/TriggersTest.java b/src/test/java/com/auth0/json/mgmt/actions/TriggersTest.java index a3781a80f..ff8c6a318 100644 --- a/src/test/java/com/auth0/json/mgmt/actions/TriggersTest.java +++ b/src/test/java/com/auth0/json/mgmt/actions/TriggersTest.java @@ -1,7 +1,7 @@ package com.auth0.json.mgmt.actions; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; diff --git a/src/test/java/com/auth0/json/mgmt/actions/VersionTest.java b/src/test/java/com/auth0/json/mgmt/actions/VersionTest.java index 0eeeedf31..dd8d70d13 100644 --- a/src/test/java/com/auth0/json/mgmt/actions/VersionTest.java +++ b/src/test/java/com/auth0/json/mgmt/actions/VersionTest.java @@ -1,10 +1,11 @@ package com.auth0.json.mgmt.actions; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; public class VersionTest extends JsonTest { diff --git a/src/test/java/com/auth0/json/mgmt/actions/VersionsPageTest.java b/src/test/java/com/auth0/json/mgmt/actions/VersionsPageTest.java index dab9b83b1..6b8809091 100644 --- a/src/test/java/com/auth0/json/mgmt/actions/VersionsPageTest.java +++ b/src/test/java/com/auth0/json/mgmt/actions/VersionsPageTest.java @@ -1,7 +1,7 @@ package com.auth0.json.mgmt.actions; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.Collections; diff --git a/src/test/java/com/auth0/json/mgmt/attackprotection/BreachedPasswordTest.java b/src/test/java/com/auth0/json/mgmt/attackprotection/BreachedPasswordTest.java index a565fdaac..139bc02b2 100644 --- a/src/test/java/com/auth0/json/mgmt/attackprotection/BreachedPasswordTest.java +++ b/src/test/java/com/auth0/json/mgmt/attackprotection/BreachedPasswordTest.java @@ -2,7 +2,7 @@ import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.Arrays; diff --git a/src/test/java/com/auth0/json/mgmt/attackprotection/BruteForceConfigurationTest.java b/src/test/java/com/auth0/json/mgmt/attackprotection/BruteForceConfigurationTest.java index 164a430f4..2a2ac0ffe 100644 --- a/src/test/java/com/auth0/json/mgmt/attackprotection/BruteForceConfigurationTest.java +++ b/src/test/java/com/auth0/json/mgmt/attackprotection/BruteForceConfigurationTest.java @@ -2,7 +2,7 @@ import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.Arrays; diff --git a/src/test/java/com/auth0/json/mgmt/attackprotection/SuspiciousIPThrottlingConfigurationTest.java b/src/test/java/com/auth0/json/mgmt/attackprotection/SuspiciousIPThrottlingConfigurationTest.java index f9a2bf031..b5d4d94cc 100644 --- a/src/test/java/com/auth0/json/mgmt/attackprotection/SuspiciousIPThrottlingConfigurationTest.java +++ b/src/test/java/com/auth0/json/mgmt/attackprotection/SuspiciousIPThrottlingConfigurationTest.java @@ -2,7 +2,7 @@ import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.Arrays; import java.util.List; diff --git a/src/test/java/com/auth0/json/mgmt/client/AddonTest.java b/src/test/java/com/auth0/json/mgmt/client/AddonTest.java index 2d2d5da53..f4cd01f4e 100644 --- a/src/test/java/com/auth0/json/mgmt/client/AddonTest.java +++ b/src/test/java/com/auth0/json/mgmt/client/AddonTest.java @@ -3,7 +3,7 @@ import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; import org.hamcrest.collection.IsMapContaining; -import org.junit.Test; +import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; diff --git a/src/test/java/com/auth0/json/mgmt/client/AddonsTest.java b/src/test/java/com/auth0/json/mgmt/client/AddonsTest.java index f50d79cbe..09745e9c8 100644 --- a/src/test/java/com/auth0/json/mgmt/client/AddonsTest.java +++ b/src/test/java/com/auth0/json/mgmt/client/AddonsTest.java @@ -2,7 +2,7 @@ import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.Collections; @@ -44,4 +44,4 @@ public void shouldDeserialize() throws Exception { assertThat(addons.getAdditionalAddons().size(), is(1)); assertThat(addons.getAdditionalAddons().get("other"), is(notNullValue())); } -} \ No newline at end of file +} diff --git a/src/test/java/com/auth0/json/mgmt/client/AndroidTest.java b/src/test/java/com/auth0/json/mgmt/client/AndroidTest.java index bbc0b136f..dc8a2f300 100644 --- a/src/test/java/com/auth0/json/mgmt/client/AndroidTest.java +++ b/src/test/java/com/auth0/json/mgmt/client/AndroidTest.java @@ -2,7 +2,7 @@ import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.Arrays; @@ -34,4 +34,4 @@ public void shouldDeserialize() throws Exception { assertThat(android.getSHA256CertFingerprints(), contains("cert1", "cert2")); assertThat(android.getSHA256CertFingerprints().size(), is(2)); } -} \ No newline at end of file +} diff --git a/src/test/java/com/auth0/json/mgmt/client/ClientTest.java b/src/test/java/com/auth0/json/mgmt/client/ClientTest.java index b46155a1c..c189d11f5 100644 --- a/src/test/java/com/auth0/json/mgmt/client/ClientTest.java +++ b/src/test/java/com/auth0/json/mgmt/client/ClientTest.java @@ -2,10 +2,14 @@ import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; +import com.auth0.json.mgmt.tokenquota.ClientCredentials; +import com.auth0.json.mgmt.tokenquota.TokenQuota; import org.hamcrest.collection.IsMapContaining; -import org.junit.Test; +import org.junit.jupiter.api.Test; +import java.time.Instant; import java.util.Collections; +import java.util.Date; import java.util.List; import java.util.Map; @@ -15,7 +19,139 @@ public class ClientTest extends JsonTest { private static final String readOnlyJson = "{\"client_id\":\"clientId\",\"is_heroku_app\":true,\"signing_keys\":[{\"cert\":\"ce\",\"pkcs7\":\"pk\",\"subject\":\"su\"}]}"; - private static final String json = "{\"name\":\"name\",\"description\":\"description\",\"client_secret\":\"secret\",\"app_type\":\"type\",\"logo_uri\":\"uri\",\"oidc_conformant\":true,\"is_first_party\":true,\"initiate_login_uri\":\"https://myhome.com/login\",\"callbacks\":[\"value\"],\"allowed_origins\":[\"value\"],\"web_origins\":[\"value\"],\"grant_types\":[\"value\"],\"client_aliases\":[\"value\"],\"allowed_clients\":[\"value\"],\"allowed_logout_urls\":[\"value\"],\"organization_usage\":\"allow\",\"organization_require_behavior\":\"no_prompt\",\"jwt_configuration\":{\"lifetime_in_seconds\":100,\"scopes\":\"openid\",\"alg\":\"alg\"},\"encryption_key\":{\"pub\":\"pub\",\"cert\":\"cert\"},\"sso\":true,\"sso_disabled\":true,\"custom_login_page_on\":true,\"custom_login_page\":\"custom\",\"custom_login_page_preview\":\"preview\",\"form_template\":\"template\",\"addons\":{\"rms\":{},\"mscrm\":{},\"slack\":{},\"layer\":{}},\"token_endpoint_auth_method\":\"method\",\"client_metadata\":{\"key\":\"value\"},\"mobile\":{\"android\":{\"app_package_name\":\"pkg\",\"sha256_cert_fingerprints\":[\"256\"]},\"ios\":{\"team_id\":\"team\",\"app_bundle_identifier\":\"id\"}},\"refresh_token\":{\"rotation_type\":\"non-rotating\"}}"; + private static final String json = "{\n" + + " \"name\": \"name\",\n" + + " \"description\": \"description\",\n" + + " \"client_secret\": \"secret\",\n" + + " \"app_type\": \"type\",\n" + + " \"logo_uri\": \"uri\",\n" + + " \"oidc_conformant\": true,\n" + + " \"is_first_party\": true,\n" + + " \"is_token_endpoint_ip_header_trusted\": true,\n" + + " \"initiate_login_uri\": \"https://myhome.com/login\",\n" + + " \"callbacks\": [\n" + + " \"value\"\n" + + " ],\n" + + " \"allowed_origins\": [\n" + + " \"value\"\n" + + " ],\n" + + " \"web_origins\": [\n" + + " \"value\"\n" + + " ],\n" + + " \"grant_types\": [\n" + + " \"value\"\n" + + " ],\n" + + " \"client_aliases\": [\n" + + " \"value\"\n" + + " ],\n" + + " \"allowed_clients\": [\n" + + " \"value\"\n" + + " ],\n" + + " \"allowed_logout_urls\": [\n" + + " \"value\"\n" + + " ],\n" + + " \"organization_usage\": \"allow\",\n" + + " \"organization_require_behavior\": \"no_prompt\",\n" + + " \"jwt_configuration\": {\n" + + " \"lifetime_in_seconds\": 100,\n" + + " \"scopes\": \"openid\",\n" + + " \"alg\": \"alg\"\n" + + " },\n" + + " \"encryption_key\": {\n" + + " \"pub\": \"pub\",\n" + + " \"cert\": \"cert\"\n" + + " },\n" + + " \"sso\": true,\n" + + " \"sso_disabled\": true,\n" + + " \"custom_login_page_on\": true,\n" + + " \"custom_login_page\": \"custom\",\n" + + " \"custom_login_page_preview\": \"preview\",\n" + + " \"form_template\": \"template\",\n" + + " \"addons\": {\n" + + " \"rms\": {},\n" + + " \"mscrm\": {},\n" + + " \"slack\": {},\n" + + " \"layer\": {}\n" + + " },\n" + + " \"token_endpoint_auth_method\": \"method\",\n" + + " \"client_metadata\": {\n" + + " \"key\": \"value\"\n" + + " },\n" + + " \"mobile\": {\n" + + " \"android\": {\n" + + " \"app_package_name\": \"pkg\",\n" + + " \"sha256_cert_fingerprints\": [\n" + + " \"256\"\n" + + " ]\n" + + " },\n" + + " \"ios\": {\n" + + " \"team_id\": \"team\",\n" + + " \"app_bundle_identifier\": \"id\"\n" + + " }\n" + + " },\n" + + " \"refresh_token\": {\n" + + " \"rotation_type\": \"non-rotating\"\n" + + " },\n" + + " \"client_authentication_methods\": {\n" + + " \"private_key_jwt\": {\n" + + " \"credentials\": [\n" + + " {\n" + + " \"id\": \"cred_abc\"\n" + + " },\n" + + " {\n" + + " \"id\": \"cred_123\"\n" + + " }\n" + + " ]\n" + + " },\n" + + " \"self_signed_tls_client_auth\": {\n" + + " \"credentials\": [\n" + + " {\n" + + " \"id\": \"cred_id\"\n" + + " }\n" + + " ]\n" + + " },\n" + + " \"tls_client_auth\": {\n" + + " \"credentials\": [\n" + + " {\n" + + " \"id\": \"cred_id\",\n" + + " \"credential_type\": \"cert_subject_dn\",\n" + + " \"name\": \"My cA mtls credential\",\n" + + " \"subject_dn\": \"subject dn\"\n" + + " }\n" + + " ]\n" + + " }\n" + + " },\n" + + " \"require_pushed_authorization_requests\": true,\n" + + " \"oidc_backchannel_logout\": {\n" + + " \"backchannel_logout_urls\": [\"http://acme.eu.auth0.com/events\"]\n" + + " },\n" + + " \"signed_request_object\": {\n" + + " \"credentials\": [\n" + + " {\n" + + " \"id\": \"cred_id\",\n" + + " \"credential_type\": \"public_key\",\n" + + " \"kid\": \"cred_kid\",\n" + + " \"alg\": \"RS256\",\n" + + " \"name\": \"My JAR credential\",\n" + + " \"created_at\": \"2024-03-14T11:34:28.893Z\",\n" + + " \"updated_at\": \"2024-03-14T11:34:28.893Z\"\n" + + " }\n" + + " ]\n" + + " },\n" + + " \"require_proof_of_possession\": true,\n" + + " \"compliance_level\": \"fapi1_adv_pkj_par\",\n" + + " \"default_organization\": {\n" + + " \"flows\": [\"client_credentials\"],\n" + + " \"organizations_id\": \"org_id\"\n" + + " },\n" + + " \"token_quota\": {\n" + + " \"client_credentials\": {\n" + + " \"per_hour\": 10,\n" + + " \"per_day\": 100,\n" + + " \"enforce\": true\n" + + " }\n" + + " }" + + "}"; @Test public void shouldSerialize() throws Exception { @@ -28,6 +164,7 @@ public void shouldSerialize() throws Exception { client.setLogoUri("uri"); client.setOIDCConformant(true); client.setIsFirstParty(true); + client.setIsTokenEndpointIpHeaderTrusted(true); List stringList = Collections.singletonList("value"); client.setCallbacks(stringList); client.setAllowedOrigins(stringList); @@ -58,6 +195,52 @@ public void shouldSerialize() throws Exception { client.setRefreshToken(refreshToken); client.setOrganizationUsage("require"); client.setOrganizationRequireBehavior("pre_login_prompt"); + client.setRequireProofOfPossession(true); + + Credential credential = new Credential("public_key", "PEM"); + PrivateKeyJwt privateKeyJwt = new PrivateKeyJwt(Collections.singletonList(credential)); + + Credential selfSignedCredential = new Credential(); + selfSignedCredential.setName("mtls credential"); + selfSignedCredential.setCredentialType("x509_cert"); + selfSignedCredential.setPem("pem"); + SelfSignedTLSClientAuth selfSignedTLSClientAuth = new SelfSignedTLSClientAuth(Collections.singletonList(selfSignedCredential)); + + Credential tlsCredential = new Credential(); + tlsCredential.setName("My cA mtls credential"); + tlsCredential.setSubjectDn("subject dn"); + tlsCredential.setCredentialType("cert_subject_dn"); + TLSClientAuth tlsClientAuth = new TLSClientAuth(Collections.singletonList(tlsCredential)); + + ClientAuthenticationMethods cam = new ClientAuthenticationMethods(privateKeyJwt, selfSignedTLSClientAuth, tlsClientAuth); + + client.setClientAuthenticationMethods(cam); + client.setRequiresPushedAuthorizationRequests(true); + client.setOidcBackchannelLogout(new OIDCBackchannelLogout(Collections.singletonList("http://acme.eu.auth0.com/events"))); + + // HRI configuration + Credential signedRequestCredential = new Credential(); + signedRequestCredential.setName("cred name"); + signedRequestCredential.setCredentialType("public_key"); + signedRequestCredential.setPem("pem"); + SignedRequest signedRequest = new SignedRequest(); + signedRequest.setRequired(true); + signedRequest.setCredentials(Collections.singletonList(signedRequestCredential)); + client.setSignedRequest(signedRequest); + client.setComplianceLevel("fapi1_adv_pkj_par"); + + ClientDefaultOrganization defaultOrganization = new ClientDefaultOrganization(); + defaultOrganization.setFlows(Collections.singletonList("client_credentials")); + defaultOrganization.setOrganizationId("org_id"); + client.setDefaultOrganization(defaultOrganization); + + ClientCredentials clientCredentials = new ClientCredentials(); + clientCredentials.setPerDay(100); + clientCredentials.setPerHour(20); + clientCredentials.setEnforce(true); + + TokenQuota tokenQuota = new TokenQuota(clientCredentials); + client.setTokenQuota(tokenQuota); String serialized = toJSON(client); assertThat(serialized, is(notNullValue())); @@ -70,6 +253,7 @@ public void shouldSerialize() throws Exception { assertThat(serialized, JsonMatcher.hasEntry("oidc_conformant", true)); assertThat(serialized, JsonMatcher.hasEntry("initiate_login_uri", "https://appzero.com/login")); assertThat(serialized, JsonMatcher.hasEntry("is_first_party", true)); + assertThat(serialized, JsonMatcher.hasEntry("is_token_endpoint_ip_header_trusted", true)); assertThat(serialized, JsonMatcher.hasEntry("callbacks", Collections.singletonList("value"))); assertThat(serialized, JsonMatcher.hasEntry("grant_types", Collections.singletonList("value"))); assertThat(serialized, JsonMatcher.hasEntry("allowed_origins", Collections.singletonList("value"))); @@ -91,6 +275,17 @@ public void shouldSerialize() throws Exception { assertThat(serialized, JsonMatcher.hasEntry("refresh_token", notNullValue())); assertThat(serialized, JsonMatcher.hasEntry("organization_usage", "require")); assertThat(serialized, JsonMatcher.hasEntry("organization_require_behavior", "pre_login_prompt")); + assertThat(serialized, JsonMatcher.hasEntry("client_authentication_methods", notNullValue())); + // but: was "{"name":"name","description":"description","client_secret":"secret","app_type":"type","logo_uri":"uri","is_first_party":true,"oidc_conformant":true,"callbacks":["value"],"allowed_origins":["value"],"web_origins":["value"],"grant_types":["value"],"client_aliases":["value"],"allowed_clients":["value"],"allowed_logout_urls":["value"],"jwt_configuration":{"lifetime_in_seconds":100,"scopes":"openid","alg":"alg"},"encryption_key":{"pub":"pub","cert":"cert"},"sso":true,"sso_disabled":true,"custom_login_page_on":true,"initiate_login_uri":"https://appzero.com/login","custom_login_page":"custom","custom_login_page_preview":"preview","form_template":"template","addons":{"rms":{},"mscrm":{},"slack":{},"layer":{}},"token_endpoint_auth_method":"method","client_metadata":{"key":"value"},"mobile":{"android":{"app_package_name":"pkg","sha256_cert_fingerprints":["256"]},"ios":{"team_id":"team","app_bundle_identifier":"id"}},"refresh_token":{},"organization_usage":"require","organization_require_behavior":"pre_login_prompt","client_authentication_methods":{"private_key_jwt":{"credentials":[{"credential_type":"public_key","pem":"PEM"}]},"self_signed_tls_client_auth":{"credentials":[{"credential_type":"x509_cert","name":"mtls credential","pem":"pem"}]},"tls_client_auth":{"credentials":[{"credential_type":"cert_subject_dn","name":"My cA mtls credential","subject_dn":"subject dn"}]}},"require_pushed_authorization_requests":true,"oidc_backchannel_logout":{"backchannel_logout_urls":["http://acme.eu.auth0.com/events"]},"signed_request_object":{"required":true,"credentials":[{"credential_type":"public_key","name":"cred name","pem":"pem"}]},"compliance_level":"fapi1_adv_pkj_par"}" + assertThat(serialized, JsonMatcher.hasEntry("client_authentication_methods", containsString("{\"private_key_jwt\":{\"credentials\":[{\"credential_type\":\"public_key\",\"pem\":\"PEM\"}]},\"self_signed_tls_client_auth\":{\"credentials\":[{\"credential_type\":\"x509_cert\",\"name\":\"mtls credential\",\"pem\":\"pem\"}]},\"tls_client_auth\":{\"credentials\":[{\"credential_type\":\"cert_subject_dn\",\"name\":\"My cA mtls credential\",\"subject_dn\":\"subject dn\"}]}}"))); + assertThat(serialized, JsonMatcher.hasEntry("require_pushed_authorization_requests", true)); + assertThat(serialized, JsonMatcher.hasEntry("oidc_backchannel_logout", containsString("{\"backchannel_logout_urls\":[\"http://acme.eu.auth0.com/events\"]}"))); + assertThat(serialized, JsonMatcher.hasEntry("signed_request_object", containsString("{\"required\":true,\"credentials\":[{\"credential_type\":\"public_key\",\"name\":\"cred name\",\"pem\":\"pem\"}]}"))); + assertThat(serialized, JsonMatcher.hasEntry("compliance_level", "fapi1_adv_pkj_par")); + assertThat(serialized, JsonMatcher.hasEntry("require_proof_of_possession", true)); + assertThat(serialized, JsonMatcher.hasEntry("default_organization", notNullValue())); + assertThat(serialized, JsonMatcher.hasEntry("token_quota", notNullValue())); + assertThat(serialized, containsString("\"token_quota\":{\"client_credentials\":{\"per_day\":100,\"per_hour\":20,\"enforce\":true}}")); } @Test @@ -106,6 +301,7 @@ public void shouldDeserialize() throws Exception { assertThat(client.isOIDCConformant(), is(true)); assertThat(client.isFirstParty(), is(true)); + assertThat(client.getIsTokenEndpointIpHeaderTrusted(), is(true)); assertThat(client.getCallbacks(), contains("value")); assertThat(client.getWebOrigins(), contains("value")); @@ -134,6 +330,46 @@ public void shouldDeserialize() throws Exception { assertThat(client.getRefreshToken(), is(notNullValue())); assertThat(client.getOrganizationUsage(), is("allow")); assertThat(client.getOrganizationRequireBehavior(), is("no_prompt")); + + assertThat(client.getClientAuthenticationMethods(), is(notNullValue())); + assertThat(client.getClientAuthenticationMethods().getPrivateKeyJwt(), is(notNullValue())); + assertThat(client.getClientAuthenticationMethods().getPrivateKeyJwt().getCredentials(), is(notNullValue())); + assertThat(client.getClientAuthenticationMethods().getPrivateKeyJwt().getCredentials().size(), is(2)); + assertThat(client.getClientAuthenticationMethods().getPrivateKeyJwt().getCredentials().get(0).getId(), is("cred_abc")); + assertThat(client.getClientAuthenticationMethods().getPrivateKeyJwt().getCredentials().get(1).getId(), is("cred_123")); + assertThat(client.getClientAuthenticationMethods().getSelfSignedTLSClientAuth(), is(notNullValue())); + assertThat(client.getClientAuthenticationMethods().getSelfSignedTLSClientAuth().getCredentials(), is(notNullValue())); + assertThat(client.getClientAuthenticationMethods().getSelfSignedTLSClientAuth().getCredentials().size(), is(1)); + assertThat(client.getClientAuthenticationMethods().getSelfSignedTLSClientAuth().getCredentials().get(0).getId(), is("cred_id")); + assertThat(client.getClientAuthenticationMethods().getTlsClientAuth(), is(notNullValue())); + assertThat(client.getClientAuthenticationMethods().getTlsClientAuth().getCredentials(), is(notNullValue())); + assertThat(client.getClientAuthenticationMethods().getTlsClientAuth().getCredentials().size(), is(1)); + assertThat(client.getClientAuthenticationMethods().getTlsClientAuth().getCredentials().get(0).getId(), is("cred_id")); + assertThat(client.getClientAuthenticationMethods().getTlsClientAuth().getCredentials().get(0).getName(), is("My cA mtls credential")); + assertThat(client.getClientAuthenticationMethods().getTlsClientAuth().getCredentials().get(0).getSubjectDn(), is("subject dn")); + assertThat(client.getClientAuthenticationMethods().getTlsClientAuth().getCredentials().get(0).getCredentialType(), is("cert_subject_dn")); + assertThat(client.getRequiresPushedAuthorizationRequests(), is(true)); + assertThat(client.getOidcBackchannelLogout().getBackchannelLogoutUrls().size(), is(1)); + + assertThat(client.getComplianceLevel(), is("fapi1_adv_pkj_par")); + assertThat(client.getSignedRequest(), is(notNullValue())); + assertThat(client.getSignedRequest().getCredentials(), is(notNullValue())); + assertThat(client.getSignedRequest().getCredentials().size(), is(1)); + assertThat(client.getSignedRequest().getCredentials().get(0).getId(), is("cred_id")); + assertThat(client.getSignedRequest().getCredentials().get(0).getCredentialType(), is("public_key")); + assertThat(client.getSignedRequest().getCredentials().get(0).getKid(), is("cred_kid")); + assertThat(client.getSignedRequest().getCredentials().get(0).getAlg(), is("RS256")); + assertThat(client.getSignedRequest().getCredentials().get(0).getName(), is("My JAR credential")); + assertThat(client.getSignedRequest().getCredentials().get(0).getCreatedAt(), is(Date.from(Instant.parse("2024-03-14T11:34:28.893Z")))); + assertThat(client.getSignedRequest().getCredentials().get(0).getUpdatedAt(), is(Date.from(Instant.parse("2024-03-14T11:34:28.893Z")))); + + assertThat(client.getRequireProofOfPossession(), is(true)); + + assertThat(client.getTokenQuota(), is(notNullValue())); + assertThat(client.getTokenQuota().getClientCredentials(), is(notNullValue())); + assertThat(client.getTokenQuota().getClientCredentials().getPerDay(), is(100)); + assertThat(client.getTokenQuota().getClientCredentials().getPerHour(), is(10)); + assertThat(client.getTokenQuota().getClientCredentials().isEnforce(), is(true)); } @Test @@ -145,4 +381,18 @@ public void shouldIncludeReadOnlyValuesOnDeserialize() throws Exception { assertThat(client.isHerokuApp(), is(true)); assertThat(client.getSigningKeys(), is(notNullValue())); } + + @Test + public void shouldCreateClientWithNameOnly() { + Client client = new Client("My App"); + assertThat(client.getName(), is("My App")); + assertThat(client.getClientId(), is(nullValue())); + } + + @Test + public void shouldCreateClientWithNameAndClientId() { + Client client = new Client("My App", "client123"); + assertThat(client.getName(), is("My App")); + assertThat(client.getClientId(), is("client123")); + } } diff --git a/src/test/java/com/auth0/json/mgmt/client/CredentialTest.java b/src/test/java/com/auth0/json/mgmt/client/CredentialTest.java new file mode 100644 index 000000000..87f95d482 --- /dev/null +++ b/src/test/java/com/auth0/json/mgmt/client/CredentialTest.java @@ -0,0 +1,63 @@ +package com.auth0.json.mgmt.client; + +import com.auth0.json.JsonMatcher; +import com.auth0.json.JsonTest; +import org.junit.jupiter.api.Test; + +import java.time.Instant; +import java.util.Date; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; + +public class CredentialTest extends JsonTest { + + private final static String JSON = "{\n" + + " \"id\": \"cred_asqwXXXIIadqq2T3zAXPwv\",\n" + + " \"name\": \"new cred\",\n" + + " \"credential_type\": \"public_key\",\n" + + " \"kid\": \"eKtBStP7BN2NiaoVrNGzb0QaRl4HlzyH1Lp00JB6Xj0\",\n" + + " \"alg\": \"RS256\",\n" + + " \"thumbprint\": \"thumb\",\n" + + " \"created_at\": \"2023-04-13T16:18:01.481Z\",\n" + + " \"updated_at\": \"2023-04-13T16:18:01.481Z\",\n" + + " \"expires_at\": \"2023-04-13T16:19:00.349Z\"\n" + + "}\n"; + + @Test + public void shouldDeserialize() throws Exception { + Credential credential = fromJSON(JSON, Credential.class); + + assertThat(credential, is(notNullValue())); + assertThat(credential.getAlg(), is("RS256")); + assertThat(credential.getCredentialType(), is("public_key")); + assertThat(credential.getExpiresAt(), is(Date.from(Instant.parse("2023-04-13T16:19:00.349Z")))); + assertThat(credential.getUpdatedAt(), is(Date.from(Instant.parse("2023-04-13T16:18:01.481Z")))); + assertThat(credential.getCreatedAt(), is(Date.from(Instant.parse("2023-04-13T16:18:01.481Z")))); + assertThat(credential.getKid(), is("eKtBStP7BN2NiaoVrNGzb0QaRl4HlzyH1Lp00JB6Xj0")); + assertThat(credential.getId(), is("cred_asqwXXXIIadqq2T3zAXPwv")); + assertThat(credential.getThumbprint(), is("thumb")); + } + + @Test + public void shouldSerialize() throws Exception { + Credential credential = new Credential("id"); + credential.setCredentialType("public_key"); + credential.setPem("pem"); + credential.setAlg("alg"); + credential.setName("name"); + credential.setParseExpiryFromCert(true); + credential.setExpiresAt(new Date()); + + String json = toJSON(credential); + assertThat(json, is(notNullValue())); + + assertThat(json, JsonMatcher.hasEntry("name", "name")); + assertThat(json, JsonMatcher.hasEntry("alg", "alg")); + assertThat(json, JsonMatcher.hasEntry("parse_expiry_from_cert", true)); + assertThat(json, JsonMatcher.hasEntry("pem", "pem")); + assertThat(json, JsonMatcher.hasEntry("credential_type", "public_key")); + assertThat(json, JsonMatcher.hasEntry("expires_at", is(notNullValue()))); + } +} diff --git a/src/test/java/com/auth0/json/mgmt/client/EncryptionKeyTest.java b/src/test/java/com/auth0/json/mgmt/client/EncryptionKeyTest.java index e76add534..ddbad4928 100644 --- a/src/test/java/com/auth0/json/mgmt/client/EncryptionKeyTest.java +++ b/src/test/java/com/auth0/json/mgmt/client/EncryptionKeyTest.java @@ -2,7 +2,7 @@ import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; @@ -34,4 +34,4 @@ public void shouldDeserialize() throws Exception { assertThat(key.getCert(), is("cert")); assertThat(key.getSubject(), is("subject")); } -} \ No newline at end of file +} diff --git a/src/test/java/com/auth0/json/mgmt/client/IOSTest.java b/src/test/java/com/auth0/json/mgmt/client/IOSTest.java index 20b05612d..fc0f28ea3 100644 --- a/src/test/java/com/auth0/json/mgmt/client/IOSTest.java +++ b/src/test/java/com/auth0/json/mgmt/client/IOSTest.java @@ -2,7 +2,7 @@ import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; @@ -31,4 +31,4 @@ public void shouldDeserialize() throws Exception { assertThat(ios.getTeamId(), is("team")); assertThat(ios.getAppBundleIdentifier(), is("identifier")); } -} \ No newline at end of file +} diff --git a/src/test/java/com/auth0/json/mgmt/client/JWTConfigurationTest.java b/src/test/java/com/auth0/json/mgmt/client/JWTConfigurationTest.java index b40b5e4e0..5918c14a5 100644 --- a/src/test/java/com/auth0/json/mgmt/client/JWTConfigurationTest.java +++ b/src/test/java/com/auth0/json/mgmt/client/JWTConfigurationTest.java @@ -3,7 +3,7 @@ import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; import org.hamcrest.collection.IsMapContaining; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.Collections; import java.util.Map; @@ -47,4 +47,4 @@ public void shouldIncludeReadOnlyValuesOnDeserialize() throws Exception { assertThat(config.isSecretEncoded(), is(true)); } -} \ No newline at end of file +} diff --git a/src/test/java/com/auth0/json/mgmt/client/MobileTest.java b/src/test/java/com/auth0/json/mgmt/client/MobileTest.java index b4262475d..6096b4343 100644 --- a/src/test/java/com/auth0/json/mgmt/client/MobileTest.java +++ b/src/test/java/com/auth0/json/mgmt/client/MobileTest.java @@ -2,7 +2,7 @@ import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; @@ -32,4 +32,4 @@ public void shouldDeserialize() throws Exception { assertThat(mobile.getAndroid(), is(notNullValue())); assertThat(mobile.getIOS(), is(notNullValue())); } -} \ No newline at end of file +} diff --git a/src/test/java/com/auth0/json/mgmt/client/RefreshTokenTest.java b/src/test/java/com/auth0/json/mgmt/client/RefreshTokenTest.java index 8987534b8..258f1dc5c 100644 --- a/src/test/java/com/auth0/json/mgmt/client/RefreshTokenTest.java +++ b/src/test/java/com/auth0/json/mgmt/client/RefreshTokenTest.java @@ -1,13 +1,13 @@ package com.auth0.json.mgmt.client; +import com.auth0.json.JsonMatcher; +import com.auth0.json.JsonTest; +import org.junit.jupiter.api.Test; + import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; -import com.auth0.json.JsonMatcher; -import com.auth0.json.JsonTest; -import org.junit.Test; - public class RefreshTokenTest extends JsonTest { private static final String json = "{\"rotation_type\":\"non-rotating\",\"expiration_type\":\"non-expiring\",\"leeway\":0,\"token_lifetime\":0,\"infinite_token_lifetime\":false,\"idle_token_lifetime\":0,\"infinite_idle_token_lifetime\":false}"; diff --git a/src/test/java/com/auth0/json/mgmt/client/SigningKeyTest.java b/src/test/java/com/auth0/json/mgmt/client/SigningKeyTest.java index fb65451f3..d4e7831c4 100644 --- a/src/test/java/com/auth0/json/mgmt/client/SigningKeyTest.java +++ b/src/test/java/com/auth0/json/mgmt/client/SigningKeyTest.java @@ -2,7 +2,7 @@ import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; @@ -32,4 +32,4 @@ public void shouldDeserialize() throws Exception { assertThat(key.getPKCS7(), is("pkcs7")); assertThat(key.getSubject(), is("subject")); } -} \ No newline at end of file +} diff --git a/src/test/java/com/auth0/json/mgmt/connections/ConnectionKeysTest.java b/src/test/java/com/auth0/json/mgmt/connections/ConnectionKeysTest.java new file mode 100644 index 000000000..764e58a5c --- /dev/null +++ b/src/test/java/com/auth0/json/mgmt/connections/ConnectionKeysTest.java @@ -0,0 +1,66 @@ +package com.auth0.json.mgmt.connections; + +import com.auth0.json.JsonMatcher; +import com.auth0.json.JsonTest; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; + +public class ConnectionKeysTest extends JsonTest { + private static final String json = "{\n" + + " \"kid\": \"kid-1\",\n" + + " \"algorithm\": \"RS256\",\n" + + " \"key_use\": \"signing\",\n" + + " \"subject_dn\": \"/CN=cajwt\",\n" + + " \"cert\": \"-----BEGIN CERTIFICATE-----\\r\\ncert-key-1\\r\\n-----END CERTIFICATE-----\\r\\n\",\n" + + " \"fingerprint\": \"F1\",\n" + + " \"thumbprint\": \"example-print\",\n" + + " \"pkcs\": \"-----BEGIN PKCS7-----\\r\\npkcs-1\\r\\n-----END PKCS7-----\\r\\n\",\n" + + " \"current\": true,\n" + + " \"current_since\": \"2025-05-29T13:17:24.850Z\"\n" + + " }"; + + @Test + public void shouldSerialize() throws Exception { + ConnectionKeys connectionKeys = new ConnectionKeys(); + connectionKeys.setKid("kid-1"); + connectionKeys.setAlgorithm("RS256"); + connectionKeys.setKeyUse("signing"); + connectionKeys.setSubjectDn("/CN=cajwt"); + connectionKeys.setFingerprint("F1"); + connectionKeys.setThumbprint("example-print"); + connectionKeys.setPkcs("pkcs"); + connectionKeys.setCurrent(true); + connectionKeys.setCurrentSince("2025-05-29T13:17:24.850Z"); + + String serialized = toJSON(connectionKeys); + assertThat(serialized, is(notNullValue())); + assertThat(serialized, JsonMatcher.hasEntry("kid", "kid-1")); + assertThat(serialized, JsonMatcher.hasEntry("algorithm", "RS256")); + assertThat(serialized, JsonMatcher.hasEntry("key_use", "signing")); + assertThat(serialized, JsonMatcher.hasEntry("subject_dn", "/CN=cajwt")); + assertThat(serialized, JsonMatcher.hasEntry("fingerprint", "F1")); + assertThat(serialized, JsonMatcher.hasEntry("thumbprint", "example-print")); + assertThat(serialized, JsonMatcher.hasEntry("pkcs", "pkcs")); + assertThat(serialized, JsonMatcher.hasEntry("current", true)); + assertThat(serialized, JsonMatcher.hasEntry("current_since", "2025-05-29T13:17:24.850Z")); + } + + @Test + public void shouldDeserialize() throws Exception { + ConnectionKeys connectionKey = fromJSON(json, ConnectionKeys.class); + assertThat(connectionKey, is(notNullValue())); + assertThat(connectionKey.getKid(), is("kid-1")); + assertThat(connectionKey.getAlgorithm(), is("RS256")); + assertThat(connectionKey.getKeyUse(), is("signing")); + assertThat(connectionKey.getSubjectDn(), is("/CN=cajwt")); + assertThat(connectionKey.getCert(), is("-----BEGIN CERTIFICATE-----\r\ncert-key-1\r\n-----END CERTIFICATE-----\r\n")); + assertThat(connectionKey.getFingerprint(), is("F1")); + assertThat(connectionKey.getThumbprint(), is("example-print")); + assertThat(connectionKey.getPkcs(), is("-----BEGIN PKCS7-----\r\npkcs-1\r\n-----END PKCS7-----\r\n")); + assertThat(connectionKey.getCurrent(), is(true)); + assertThat(connectionKey.getCurrentSince(), is("2025-05-29T13:17:24.850Z")); + } +} diff --git a/src/test/java/com/auth0/json/mgmt/ConnectionTest.java b/src/test/java/com/auth0/json/mgmt/connections/ConnectionTest.java similarity index 80% rename from src/test/java/com/auth0/json/mgmt/ConnectionTest.java rename to src/test/java/com/auth0/json/mgmt/connections/ConnectionTest.java index 901171eb2..529f3a86e 100644 --- a/src/test/java/com/auth0/json/mgmt/ConnectionTest.java +++ b/src/test/java/com/auth0/json/mgmt/connections/ConnectionTest.java @@ -1,8 +1,8 @@ -package com.auth0.json.mgmt; +package com.auth0.json.mgmt.connections; import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.Arrays; import java.util.HashMap; @@ -22,7 +22,8 @@ public void shouldSerialize() throws Exception { Connection connection = new Connection("my-connection", "auth0"); connection.setDisplayName("COOL!"); connection.setOptions(new HashMap()); - connection.setEnabledClients(Arrays.asList("client1", "client2")); + // enabled_clients is deprecated as part of the new connections API GET/PATCH Enabled Clients +// connection.setEnabledClients(Arrays.asList("client1", "client2")); connection.setMetadata(new HashMap()); connection.setRealms(Arrays.asList("realm1", "realm2")); @@ -32,7 +33,8 @@ public void shouldSerialize() throws Exception { assertThat(serialized, JsonMatcher.hasEntry("display_name", "COOL!")); assertThat(serialized, JsonMatcher.hasEntry("strategy", "auth0")); assertThat(serialized, JsonMatcher.hasEntry("options", notNullValue())); - assertThat(serialized, JsonMatcher.hasEntry("enabled_clients", Arrays.asList("client1", "client2"))); + // enabled_clients is deprecated as part of the new connections API GET/PATCH Enabled Clients +// assertThat(serialized, JsonMatcher.hasEntry("enabled_clients", Arrays.asList("client1", "client2"))); assertThat(serialized, JsonMatcher.hasEntry("provisioning_ticket_url", null)); assertThat(serialized, JsonMatcher.hasEntry("metadata", notNullValue())); assertThat(serialized, JsonMatcher.hasEntry("realms", Arrays.asList("realm1", "realm2"))); @@ -47,7 +49,8 @@ public void shouldDeserialize() throws Exception { assertThat(connection.getDisplayName(), is("My cool connection!")); assertThat(connection.getOptions(), is(notNullValue())); assertThat(connection.getStrategy(), is("auth0")); - assertThat(connection.getEnabledClients(), contains("client1", "client2")); + // enabled_clients is deprecated as part of the new connections API GET/PATCH Enabled Clients +// assertThat(connection.getEnabledClients(), contains("client1", "client2")); assertThat(connection.getProvisioningTicketUrl(), is(nullValue())); assertThat(connection.getMetadata(), is(notNullValue())); assertThat(connection.getRealms(), contains("realm1", "realm2")); @@ -61,7 +64,8 @@ public void shouldDeserializeAd() throws Exception { assertThat(connection.getName(), is("my-ad-connection")); assertThat(connection.getOptions(), is(notNullValue())); assertThat(connection.getStrategy(), is("ad")); - assertThat(connection.getEnabledClients(), contains("client1", "client2")); + // enabled_clients is deprecated as part of the new connections API GET/PATCH Enabled Clients + //assertThat(connection.getEnabledClients(), contains("client1", "client2")); assertThat(connection.getProvisioningTicketUrl(), is("https://demo.auth0.com/p/ad/ddQTRlVt")); assertThat(connection.getMetadata(), is(nullValue())); } diff --git a/src/test/java/com/auth0/json/mgmt/connections/EnabledClientRequestTest.java b/src/test/java/com/auth0/json/mgmt/connections/EnabledClientRequestTest.java new file mode 100644 index 000000000..46164f764 --- /dev/null +++ b/src/test/java/com/auth0/json/mgmt/connections/EnabledClientRequestTest.java @@ -0,0 +1,23 @@ +package com.auth0.json.mgmt.connections; + +import com.auth0.json.JsonMatcher; +import com.auth0.json.JsonTest; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; + +public class EnabledClientRequestTest extends JsonTest { + private static final String json = "{\"client_id\":\"1\",\"status\":true}"; + + @Test + public void shouldSerialize() throws Exception { + EnabledClientRequest enabledClientRequest = new EnabledClientRequest("1", true); + + String serialized = toJSON(enabledClientRequest); + assertThat(serialized, is(notNullValue())); + assertThat(serialized, JsonMatcher.hasEntry("client_id", "1")); + assertThat(serialized, JsonMatcher.hasEntry("status", true)); + } + +} diff --git a/src/test/java/com/auth0/json/mgmt/connections/EnabledClientResponseTest.java b/src/test/java/com/auth0/json/mgmt/connections/EnabledClientResponseTest.java new file mode 100644 index 000000000..e304f7140 --- /dev/null +++ b/src/test/java/com/auth0/json/mgmt/connections/EnabledClientResponseTest.java @@ -0,0 +1,40 @@ +package com.auth0.json.mgmt.connections; + +import com.auth0.json.JsonMatcher; +import com.auth0.json.JsonTest; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; + +public class EnabledClientResponseTest extends JsonTest { + private static final String json = "src/test/resources/mgmt/enabled_clients_for_connection.json"; + + @Test + public void shouldSerialize() throws Exception { + EnabledClientResponse enabledClientResponse = new EnabledClientResponse(); + List clientsList = new ArrayList<>(); + clientsList.add(new Clients("client-1")); + clientsList.add(new Clients("client-2")); + enabledClientResponse.setClients(clientsList); + enabledClientResponse.setNext("next"); + + String serialized = toJSON(enabledClientResponse); + assertThat(serialized, is(notNullValue())); + assertThat(serialized, JsonMatcher.hasEntry("next", "next")); + } + + @Test + public void shouldDeserialize() throws Exception { + EnabledClientResponse deserialized = fromJSON(readTextFile(json), EnabledClientResponse.class); + + assertThat(deserialized, is(notNullValue())); + assertThat(deserialized.getClients().get(0).getClientId(), is("client-1")); + assertThat(deserialized.getClients().get(1).getClientId(), is("client-2")); + assertThat(deserialized.getNext(), is("next")); + } +} diff --git a/src/test/java/com/auth0/json/mgmt/connections/RotateKeyTest.java b/src/test/java/com/auth0/json/mgmt/connections/RotateKeyTest.java new file mode 100644 index 000000000..570e163d2 --- /dev/null +++ b/src/test/java/com/auth0/json/mgmt/connections/RotateKeyTest.java @@ -0,0 +1,35 @@ +package com.auth0.json.mgmt.connections; + +import com.auth0.json.JsonMatcher; +import com.auth0.json.JsonTest; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; + +public class RotateKeyTest extends JsonTest { + private static final String json = "src/test/resources/mgmt/rotate_key.json"; + + @Test + public void shouldSerialize() throws Exception { + RotateKey rotateKey = new RotateKey(); + rotateKey.setCert("-----BEGIN CERTIFICATE-----cert-key-----END CERTIFICATE-----"); + rotateKey.setKid("kid-1"); + + String serialized = toJSON(rotateKey); + assertThat(serialized, is(notNullValue())); + assertThat(serialized, JsonMatcher.hasEntry("cert", "-----BEGIN CERTIFICATE-----cert-key-----END CERTIFICATE-----")); + assertThat(serialized, JsonMatcher.hasEntry("kid", "kid-1")); + } + + @Test + public void shouldDeserialize() throws Exception { + RotateKey deserialized = fromJSON(readTextFile(json), RotateKey.class); + + assertThat(deserialized, is(notNullValue())); + assertThat(deserialized.getCert(), is("-----BEGIN CERTIFICATE-----cert-key-----END CERTIFICATE-----")); + assertThat(deserialized.getKid(), is("kid-1")); + + } +} diff --git a/src/test/java/com/auth0/json/mgmt/connections/ScimConfigurationRequestTest.java b/src/test/java/com/auth0/json/mgmt/connections/ScimConfigurationRequestTest.java new file mode 100644 index 000000000..2eaf80151 --- /dev/null +++ b/src/test/java/com/auth0/json/mgmt/connections/ScimConfigurationRequestTest.java @@ -0,0 +1,51 @@ +package com.auth0.json.mgmt.connections; + +import com.auth0.json.JsonMatcher; +import com.auth0.json.JsonTest; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; + +public class ScimConfigurationRequestTest extends JsonTest { + + private final static String json = "{\n" + + " \"user_id_attribute\": \"externalId\",\n" + + " \"mapping\": [\n" + + " {\n" + + " \"auth0\": \"preferred_username\",\n" + + " \"scim\": \"userName\"\n" + + " }\n" + + " ]\n" + + "}"; + + @Test + public void serialize() throws Exception { + ScimConfigurationRequest request = new ScimConfigurationRequest(); + request.setUserIdAttribute("externalId"); + List mappingList = new ArrayList<>(); + Mapping mapping = new Mapping("preferred_username", "userName"); + mappingList.add(mapping); + request.setMapping(mappingList); + + String serialized = toJSON(request); + assertThat(serialized, is(notNullValue())); + assertThat(serialized, JsonMatcher.hasEntry("user_id_attribute", "externalId")); + assertThat(serialized, JsonMatcher.hasEntry("mapping", notNullValue())); + assertThat(serialized, containsString("\"mapping\":[{\"auth0\":\"preferred_username\",\"scim\":\"userName\"}]")); + } + + @Test + public void deserialize() throws Exception { + ScimConfigurationRequest deserialized = fromJSON(json, ScimConfigurationRequest.class); + + assertThat(deserialized, is(notNullValue())); + + assertThat(deserialized.getUserIdAttribute(), is("externalId")); + assertThat(deserialized.getMapping().get(0).getAuth0(), is("preferred_username")); + assertThat(deserialized.getMapping().get(0).getScim(), is("userName")); + } +} diff --git a/src/test/java/com/auth0/json/mgmt/connections/ScimConfigurationResponseTest.java b/src/test/java/com/auth0/json/mgmt/connections/ScimConfigurationResponseTest.java new file mode 100644 index 000000000..5aa5f5855 --- /dev/null +++ b/src/test/java/com/auth0/json/mgmt/connections/ScimConfigurationResponseTest.java @@ -0,0 +1,66 @@ +package com.auth0.json.mgmt.connections; + +import com.auth0.json.JsonTest; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; + +import static com.auth0.json.JsonMatcher.hasEntry; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; + +public class ScimConfigurationResponseTest extends JsonTest { + private final static String SCIM_CONFIGURATION_RESPONSE_JSON = "src/test/resources/mgmt/connection_scim_configuration.json"; + + @Test + public void deserialize() throws Exception { + ScimConfigurationResponse deserialized = fromJSON(readTextFile(SCIM_CONFIGURATION_RESPONSE_JSON), ScimConfigurationResponse.class); + + assertThat(deserialized.getTenantName(), is("dev-1")); + assertThat(deserialized.getConnectionId(), is("con_0000000000000001")); + assertThat(deserialized.getConnectionName(), is("New Connection")); + assertThat(deserialized.getStrategy(), is("okta")); + assertThat(deserialized.getMapping().get(0).getAuth0(), is("preferred_username")); + assertThat(deserialized.getMapping().get(0).getScim(), is("userName")); + assertThat(deserialized.getMapping().get(1).getAuth0(), is("email")); + assertThat(deserialized.getMapping().get(1).getScim(), is("emails[primary eq true].value")); + assertThat(deserialized.getUpdatedOn(), is("2025-01-22T11:56:24.461Z")); + assertThat(deserialized.getCreatedAt(), is("2025-01-22T11:56:24.461Z")); + assertThat(deserialized.getUserIdAttribute(), is("externalId")); + } + + @Test + public void serialize() throws Exception { + ScimConfigurationResponse scimConfigurationResponse = new ScimConfigurationResponse(); + scimConfigurationResponse.setTenantName("dev-1"); + scimConfigurationResponse.setConnectionId("con_0000000000000001"); + scimConfigurationResponse.setConnectionName("New Connection"); + scimConfigurationResponse.setStrategy("okta"); + + List mappingList = new ArrayList<>(); + Mapping mapping1 = new Mapping("preferred_username", "userName"); + mappingList.add(mapping1); + Mapping mapping2 = new Mapping("email", "emails[primary eq true].value"); + mappingList.add(mapping2); + scimConfigurationResponse.setMapping(mappingList); + + scimConfigurationResponse.setUpdatedOn("2025-01-22T11:56:24.461Z"); + scimConfigurationResponse.setCreatedAt("2025-01-22T11:56:24.461Z"); + scimConfigurationResponse.setUserIdAttribute("externalId"); + + String serialized = toJSON(scimConfigurationResponse); + assertThat(serialized, is(notNullValue())); + + assertThat(serialized, hasEntry("tenant_name", "dev-1")); + assertThat(serialized, hasEntry("connection_id", "con_0000000000000001")); + assertThat(serialized, hasEntry("connection_name", "New Connection")); + assertThat(serialized, hasEntry("strategy", "okta")); + assertThat(serialized, hasEntry("mapping", notNullValue())); + assertThat(serialized, containsString("\"mapping\":[{\"auth0\":\"preferred_username\",\"scim\":\"userName\"},{\"auth0\":\"email\",\"scim\":\"emails[primary eq true].value\"}]")); + assertThat(serialized, hasEntry("updated_on", "2025-01-22T11:56:24.461Z")); + assertThat(serialized, hasEntry("created_at", "2025-01-22T11:56:24.461Z")); + assertThat(serialized, hasEntry("user_id_attribute", "externalId")); + } +} + diff --git a/src/test/java/com/auth0/json/mgmt/connections/ScimTokenBaseResponseTest.java b/src/test/java/com/auth0/json/mgmt/connections/ScimTokenBaseResponseTest.java new file mode 100644 index 000000000..98716f53d --- /dev/null +++ b/src/test/java/com/auth0/json/mgmt/connections/ScimTokenBaseResponseTest.java @@ -0,0 +1,56 @@ +package com.auth0.json.mgmt.connections; + +import com.auth0.json.JsonMatcher; +import com.auth0.json.JsonTest; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; + +import static com.auth0.json.JsonMatcher.hasEntry; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; + +public class ScimTokenBaseResponseTest extends JsonTest { + + private final static String json = "{\n" + + " \"token_id\": \"tok_000000001\",\n" + + " \"scopes\": [\n" + + " \"get:users\"\n" + + " ],\n" + + " \"created_at\": \"2025-01-23T12:34:46.321Z\",\n" + + " \"valid_until\": \"2025-01-23T12:51:26.321Z\"\n" + + "}"; + + + @Test + public void serialize() throws Exception { + ScimTokenBaseResponse request = new ScimTokenBaseResponse(); + request.setTokenId("tok_000000001"); + List scopes = new ArrayList<>(); + scopes.add("get:users"); + request.setScopes(scopes); + request.setCreatedAt("2025-01-23T12:34:46.321Z"); + request.setValidUntil("2025-01-23T12:51:26.321Z"); + + String serialized = toJSON(request); + assertThat(serialized, is(notNullValue())); + assertThat(serialized, JsonMatcher.hasEntry("token_id", "tok_000000001")); + assertThat(serialized, hasEntry("scopes", notNullValue())); + assertThat(serialized, containsString("\"scopes\":[\"get:users\"]")); + assertThat(serialized, JsonMatcher.hasEntry("created_at", "2025-01-23T12:34:46.321Z")); + assertThat(serialized, JsonMatcher.hasEntry("valid_until", "2025-01-23T12:51:26.321Z")); + } + + @Test + public void deserialize() throws Exception { + ScimTokenBaseResponse deserialized = fromJSON(json, ScimTokenBaseResponse.class); + + assertThat(deserialized, is(notNullValue())); + + assertThat(deserialized.getTokenId(), is("tok_000000001")); + assertThat(deserialized.getScopes().get(0), is("get:users")); + assertThat(deserialized.getCreatedAt(), is("2025-01-23T12:34:46.321Z")); + assertThat(deserialized.getValidUntil(), is("2025-01-23T12:51:26.321Z")); + } +} diff --git a/src/test/java/com/auth0/json/mgmt/connections/ScimTokenCreateResponseTest.java b/src/test/java/com/auth0/json/mgmt/connections/ScimTokenCreateResponseTest.java new file mode 100644 index 000000000..45287acb8 --- /dev/null +++ b/src/test/java/com/auth0/json/mgmt/connections/ScimTokenCreateResponseTest.java @@ -0,0 +1,48 @@ +package com.auth0.json.mgmt.connections; + +import com.auth0.json.JsonTest; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; + +import static com.auth0.json.JsonMatcher.hasEntry; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; + +public class ScimTokenCreateResponseTest extends JsonTest { + public static final String CONNECTION_SCIM_TOKEN = "src/test/resources/mgmt/connection_scim_token.json"; + + @Test + public void deserialize() throws Exception { + ScimTokenCreateResponse deserialized = fromJSON(readTextFile(CONNECTION_SCIM_TOKEN), ScimTokenCreateResponse.class); + + assertThat(deserialized.getTokenId(), is("tok_000000001")); + assertThat(deserialized.getToken(), is("tok_iwioqiwoqoqiwqoiwqwi")); + assertThat(deserialized.getScopes().get(0), is("get:users")); + assertThat(deserialized.getCreatedAt(), is("2025-01-23T12:34:46.321Z")); + assertThat(deserialized.getValidUntil(), is("2025-01-23T12:51:26.321Z")); + } + + @Test + public void serialize() throws Exception { + ScimTokenCreateResponse serialize = new ScimTokenCreateResponse(); + serialize.setTokenId("tok_000000001"); + serialize.setToken("tok_iwioqiwoqoqiwqoiwqwi"); + List scopes = new ArrayList<>(); + scopes.add("get:users"); + serialize.setScopes(scopes); + serialize.setCreatedAt("2025-01-23T12:34:46.321Z"); + serialize.setValidUntil("2025-01-23T12:51:26.321Z"); + + String serialized = toJSON(serialize); + assertThat(serialized, is(notNullValue())); + + assertThat(serialized, hasEntry("token_id", "tok_000000001")); + assertThat(serialized, hasEntry("token", "tok_iwioqiwoqoqiwqoiwqwi")); + assertThat(serialized, hasEntry("scopes", notNullValue())); + assertThat(serialized, containsString("\"scopes\":[\"get:users\"]")); + assertThat(serialized, hasEntry("created_at", "2025-01-23T12:34:46.321Z")); + assertThat(serialized, hasEntry("valid_until", "2025-01-23T12:51:26.321Z")); + } +} diff --git a/src/test/java/com/auth0/json/mgmt/connections/ScimTokenRequestTest.java b/src/test/java/com/auth0/json/mgmt/connections/ScimTokenRequestTest.java new file mode 100644 index 000000000..ca2769794 --- /dev/null +++ b/src/test/java/com/auth0/json/mgmt/connections/ScimTokenRequestTest.java @@ -0,0 +1,44 @@ +package com.auth0.json.mgmt.connections; + +import com.auth0.json.JsonTest; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; + +import static com.auth0.json.JsonMatcher.hasEntry; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; + +public class ScimTokenRequestTest extends JsonTest { + + public static final String json = "{\n" + + " \"scopes\": [\"get:users\"],\n" + + " \"token_lifetime\": 1000\n" + + "}"; + + @Test + public void serialize() throws Exception { + ScimTokenRequest request = new ScimTokenRequest(); + request.setTokenLifetime(1000); + List scopes = new ArrayList<>(); + scopes.add("get:users"); + request.setScopes(scopes); + + String serialized = toJSON(request); + assertThat(serialized, is(notNullValue())); + assertThat(serialized, hasEntry("scopes", notNullValue())); + assertThat(serialized, containsString("\"scopes\":[\"get:users\"]")); + assertThat(serialized, hasEntry("token_lifetime", 1000)); + } + + @Test + public void deserialize() throws Exception { + ScimTokenRequest deserialized = fromJSON(json, ScimTokenRequest.class); + + assertThat(deserialized, is(notNullValue())); + + assertThat(deserialized.getTokenLifetime(), is(1000)); + assertThat(deserialized.getScopes().get(0), is("get:users")); + } +} diff --git a/src/test/java/com/auth0/json/mgmt/connections/ScimTokenResponseTest.java b/src/test/java/com/auth0/json/mgmt/connections/ScimTokenResponseTest.java new file mode 100644 index 000000000..5924570b2 --- /dev/null +++ b/src/test/java/com/auth0/json/mgmt/connections/ScimTokenResponseTest.java @@ -0,0 +1,60 @@ +package com.auth0.json.mgmt.connections; + +import com.auth0.json.JsonMatcher; +import com.auth0.json.JsonTest; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; + +import static com.auth0.json.JsonMatcher.hasEntry; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.is; + +public class ScimTokenResponseTest extends JsonTest { + private final static String json = "{\n" + + " \"token_id\": \"tok_000000001\",\n" + + " \"scopes\": [\n" + + " \"get:users\"\n" + + " ],\n" + + " \"created_at\": \"2025-01-23T12:34:46.321Z\",\n" + + " \"valid_until\": \"2025-01-23T12:51:26.321Z\",\n" + + " \"last_used_at\": \"2025-01-23T12:51:26.321Z\"\n" + + "}"; + + + @Test + public void serialize() throws Exception { + ScimTokenResponse request = new ScimTokenResponse(); + request.setTokenId("tok_000000001"); + List scopes = new ArrayList<>(); + scopes.add("get:users"); + request.setScopes(scopes); + request.setCreatedAt("2025-01-23T12:34:46.321Z"); + request.setValidUntil("2025-01-23T12:51:26.321Z"); + request.setLastUsedAt("2025-01-23T12:51:26.321Z"); + + String serialized = toJSON(request); + assertThat(serialized, is(notNullValue())); + assertThat(serialized, JsonMatcher.hasEntry("token_id", "tok_000000001")); + assertThat(serialized, hasEntry("scopes", notNullValue())); + assertThat(serialized, containsString("\"scopes\":[\"get:users\"]")); + assertThat(serialized, JsonMatcher.hasEntry("created_at", "2025-01-23T12:34:46.321Z")); + assertThat(serialized, JsonMatcher.hasEntry("valid_until", "2025-01-23T12:51:26.321Z")); + assertThat(serialized, JsonMatcher.hasEntry("last_used_at", "2025-01-23T12:51:26.321Z")); + } + + @Test + public void deserialize() throws Exception { + ScimTokenResponse deserialized = fromJSON(json, ScimTokenResponse.class); + + assertThat(deserialized, is(notNullValue())); + + assertThat(deserialized.getTokenId(), is("tok_000000001")); + assertThat(deserialized.getScopes().get(0), is("get:users")); + assertThat(deserialized.getCreatedAt(), is("2025-01-23T12:34:46.321Z")); + assertThat(deserialized.getValidUntil(), is("2025-01-23T12:51:26.321Z")); + assertThat(deserialized.getLastUsedAt(), is("2025-01-23T12:51:26.321Z")); + } +} diff --git a/src/test/java/com/auth0/json/mgmt/emailproviders/EmailProviderCredentialsTest.java b/src/test/java/com/auth0/json/mgmt/emailproviders/EmailProviderCredentialsTest.java index cf3f233c9..29a642b82 100644 --- a/src/test/java/com/auth0/json/mgmt/emailproviders/EmailProviderCredentialsTest.java +++ b/src/test/java/com/auth0/json/mgmt/emailproviders/EmailProviderCredentialsTest.java @@ -2,7 +2,7 @@ import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; @@ -52,4 +52,4 @@ public void shouldDeserialize() throws Exception { assertThat(credentials.getSMTPUser(), is("usr")); assertThat(credentials.getSMTPPass(), is("pwd")); } -} \ No newline at end of file +} diff --git a/src/test/java/com/auth0/json/mgmt/emailproviders/EmailProviderTest.java b/src/test/java/com/auth0/json/mgmt/emailproviders/EmailProviderTest.java index 20e72c658..e387e36e5 100644 --- a/src/test/java/com/auth0/json/mgmt/emailproviders/EmailProviderTest.java +++ b/src/test/java/com/auth0/json/mgmt/emailproviders/EmailProviderTest.java @@ -2,7 +2,7 @@ import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.Collections; diff --git a/src/test/java/com/auth0/json/mgmt/guardian/EnrollmentTest.java b/src/test/java/com/auth0/json/mgmt/guardian/EnrollmentTest.java index b940eb78a..5909e3482 100644 --- a/src/test/java/com/auth0/json/mgmt/guardian/EnrollmentTest.java +++ b/src/test/java/com/auth0/json/mgmt/guardian/EnrollmentTest.java @@ -1,7 +1,7 @@ package com.auth0.json.mgmt.guardian; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; @@ -26,4 +26,4 @@ public void shouldDeserialize() throws Exception { assertThat(enrollment.getEnrolledAt(), is(parseJSONDate("2016-02-23T19:57:29.532Z"))); assertThat(enrollment.getLastAuth(), is(parseJSONDate("2016-02-23T19:57:29.532Z"))); } -} \ No newline at end of file +} diff --git a/src/test/java/com/auth0/json/mgmt/guardian/EnrollmentTicketTest.java b/src/test/java/com/auth0/json/mgmt/guardian/EnrollmentTicketTest.java index 02b36f664..a4330a881 100644 --- a/src/test/java/com/auth0/json/mgmt/guardian/EnrollmentTicketTest.java +++ b/src/test/java/com/auth0/json/mgmt/guardian/EnrollmentTicketTest.java @@ -2,7 +2,7 @@ import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; @@ -50,4 +50,4 @@ public void shouldIncludeReadOnlyValuesOnDeserialize() throws Exception { assertThat(ticket.getTicketId(), is("ticket123")); assertThat(ticket.getTicketUrl(), is("https://auth0.com/guardian/tickets/123")); } -} \ No newline at end of file +} diff --git a/src/test/java/com/auth0/json/mgmt/guardian/FactorTest.java b/src/test/java/com/auth0/json/mgmt/guardian/FactorTest.java index 5edcf42d0..2f8d5ce1f 100644 --- a/src/test/java/com/auth0/json/mgmt/guardian/FactorTest.java +++ b/src/test/java/com/auth0/json/mgmt/guardian/FactorTest.java @@ -2,7 +2,7 @@ import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; @@ -30,4 +30,4 @@ public void shouldDeserialize() throws Exception { assertThat(factor.getName(), is("sms")); assertThat(factor.isTrialExpired(), is(true)); } -} \ No newline at end of file +} diff --git a/src/test/java/com/auth0/json/mgmt/guardian/GuardianTemplatesTest.java b/src/test/java/com/auth0/json/mgmt/guardian/GuardianTemplatesTest.java index 2b9097cca..8d9e9e434 100644 --- a/src/test/java/com/auth0/json/mgmt/guardian/GuardianTemplatesTest.java +++ b/src/test/java/com/auth0/json/mgmt/guardian/GuardianTemplatesTest.java @@ -2,7 +2,7 @@ import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; @@ -30,4 +30,4 @@ public void shouldDeserialize() throws Exception { assertThat(templates.getVerificationMessage(), is("verifyme")); } -} \ No newline at end of file +} diff --git a/src/test/java/com/auth0/json/mgmt/guardian/SNSFactorProviderTest.java b/src/test/java/com/auth0/json/mgmt/guardian/SNSFactorProviderTest.java index ef87e66e4..d8acbbd5c 100644 --- a/src/test/java/com/auth0/json/mgmt/guardian/SNSFactorProviderTest.java +++ b/src/test/java/com/auth0/json/mgmt/guardian/SNSFactorProviderTest.java @@ -2,7 +2,7 @@ import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; @@ -15,12 +15,7 @@ public class SNSFactorProviderTest extends JsonTest { @SuppressWarnings("deprecation") @Test public void shouldSerializeWithDeprecatedSetters() throws Exception { - SNSFactorProvider provider = new SNSFactorProvider(); - provider.setAWSRegion("ar"); - provider.setAWSAccessKeyId("akey"); - provider.setAWSSecretAccessKey("secretakey"); - provider.setSNSAPNSPlatformApplicationARN("arn1"); - provider.setSNSGCMPlatformApplicationARN("arn2"); + SNSFactorProvider provider = new SNSFactorProvider("akey", "secretakey", "ar", "arn1", "arn2"); String serialized = toJSON(provider); assertThat(serialized, is(notNullValue())); @@ -56,4 +51,4 @@ public void shouldDeserialize() throws Exception { assertThat(provider.getSNSGCMPlatformApplicationARN(), is("arn2")); } -} \ No newline at end of file +} diff --git a/src/test/java/com/auth0/json/mgmt/guardian/TwilioFactorProviderTest.java b/src/test/java/com/auth0/json/mgmt/guardian/TwilioFactorProviderTest.java index 7849d55b1..508a1b788 100644 --- a/src/test/java/com/auth0/json/mgmt/guardian/TwilioFactorProviderTest.java +++ b/src/test/java/com/auth0/json/mgmt/guardian/TwilioFactorProviderTest.java @@ -2,59 +2,28 @@ import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; +import org.junit.jupiter.api.Test; +import static com.auth0.AssertsUtil.verifyThrows; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; public class TwilioFactorProviderTest extends JsonTest { - @SuppressWarnings("deprecation") - @Rule - public ExpectedException exception = ExpectedException.none(); - private static final String JSON_WITH_FROM = "{\"from\":\"+12356789\",\"auth_token\":\"atokEn\",\"sid\":\"id123\"}"; private static final String JSON_WITH_MESSAGING_SERVICE_SID = "{\"messaging_service_sid\":\"id321\",\"auth_token\":\"atokEn\",\"sid\":\"id123\"}"; @Test public void shouldFailConstructionWithBothFromAndMessagingServiceSID() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("You must specify either `from` or `messagingServiceSID`, but not both"); - - new TwilioFactorProvider("+12356789", "messaging_service_sid", "atokEn", "id123"); - } - - @SuppressWarnings("deprecation") - @Test - public void shouldFailWhenSettingFromAndMessagingServiceSIDWasAlreadySet() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("You must specify either `from` or `messagingServiceSID`, but not both"); - - TwilioFactorProvider provider = new TwilioFactorProvider(); - provider.setFrom("+12356789"); - provider.setMessagingServiceSID("id321"); - } - - @SuppressWarnings("deprecation") - @Test - public void shouldFailWhenSettingMessagingServiceSIDAndFromWasAlreadySet() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("You must specify either `from` or `messagingServiceSID`, but not both"); - - TwilioFactorProvider provider = new TwilioFactorProvider(); - provider.setMessagingServiceSID("id321"); - provider.setFrom("+12356789"); + verifyThrows(IllegalArgumentException.class, + () -> new TwilioFactorProvider("+12356789", "messaging_service_sid", "atokEn", "id123"), + "You must specify either `from` or `messagingServiceSID`, but not both"); } @SuppressWarnings("deprecation") @Test public void shouldSerializeWithDeprecatedSettersWithFrom() throws Exception { - TwilioFactorProvider provider = new TwilioFactorProvider(); - provider.setAuthToken("atokEn"); - provider.setFrom("+12356789"); - provider.setSID("id123"); + TwilioFactorProvider provider = new TwilioFactorProvider("+12356789", null, "atokEn", "id123"); String serialized = toJSON(provider); assertThat(serialized, is(notNullValue())); @@ -67,10 +36,7 @@ public void shouldSerializeWithDeprecatedSettersWithFrom() throws Exception { @SuppressWarnings("deprecation") @Test public void shouldSerializeWithDeprecatedSettersWithMessagingServiceSID() throws Exception { - TwilioFactorProvider provider = new TwilioFactorProvider(); - provider.setAuthToken("atokEn"); - provider.setMessagingServiceSID("id321"); - provider.setSID("id123"); + TwilioFactorProvider provider = new TwilioFactorProvider(null, "id321", "atokEn", "id123"); String serialized = toJSON(provider); assertThat(serialized, is(notNullValue())); diff --git a/src/test/java/com/auth0/json/mgmt/jobs/JobErrorDetailsTest.java b/src/test/java/com/auth0/json/mgmt/jobs/JobErrorDetailsTest.java index 9f33a9737..69c8ac551 100644 --- a/src/test/java/com/auth0/json/mgmt/jobs/JobErrorDetailsTest.java +++ b/src/test/java/com/auth0/json/mgmt/jobs/JobErrorDetailsTest.java @@ -1,17 +1,14 @@ package com.auth0.json.mgmt.jobs; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.hasSize; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.notNullValue; - -import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; import com.auth0.json.mgmt.users.User; import com.fasterxml.jackson.core.JsonProcessingException; +import org.junit.jupiter.api.Test; + import java.util.Collections; -import org.junit.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; public class JobErrorDetailsTest extends JsonTest { diff --git a/src/test/java/com/auth0/json/mgmt/jobs/JobTest.java b/src/test/java/com/auth0/json/mgmt/jobs/JobTest.java index 7f50c4ea1..f7e1f7363 100644 --- a/src/test/java/com/auth0/json/mgmt/jobs/JobTest.java +++ b/src/test/java/com/auth0/json/mgmt/jobs/JobTest.java @@ -3,11 +3,11 @@ import com.auth0.json.JsonTest; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; -import org.junit.Test; +import org.junit.jupiter.api.Test; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.core.Is.is; -import static org.hamcrest.MatcherAssert.assertThat; public class JobTest extends JsonTest { diff --git a/src/test/java/com/auth0/json/mgmt/jobs/UsersExportFieldTest.java b/src/test/java/com/auth0/json/mgmt/jobs/UsersExportFieldTest.java index 1f6e5277e..0a77740be 100644 --- a/src/test/java/com/auth0/json/mgmt/jobs/UsersExportFieldTest.java +++ b/src/test/java/com/auth0/json/mgmt/jobs/UsersExportFieldTest.java @@ -3,12 +3,12 @@ import com.auth0.json.JsonTest; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; -import org.junit.Test; +import org.junit.jupiter.api.Test; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.core.Is.is; -import static org.hamcrest.MatcherAssert.assertThat; public class UsersExportFieldTest extends JsonTest { diff --git a/src/test/java/com/auth0/json/mgmt/keys/EncryptionKeyTest.java b/src/test/java/com/auth0/json/mgmt/keys/EncryptionKeyTest.java new file mode 100644 index 000000000..31d08a463 --- /dev/null +++ b/src/test/java/com/auth0/json/mgmt/keys/EncryptionKeyTest.java @@ -0,0 +1,70 @@ +package com.auth0.json.mgmt.keys; + +import com.auth0.json.JsonMatcher; +import com.auth0.json.JsonTest; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; + +public class EncryptionKeyTest extends JsonTest { + + private static final String json = "{\n" + + " \"kid\": \"kid\",\n" + + " \"type\": \"tenant-master-key\",\n" + + " \"state\": \"active\",\n" + + " \"created_at\": \"2024-10-16T10:50:44.107Z\",\n" + + " \"updated_at\": \"2024-10-24T06:47:24.899Z\",\n" + + " \"parent_kid\": \"pkid\",\n" + + " \"public_key\": \"pkey\"\n" + + "}"; + + private static final String readOnlyJson = "{\n" + + " \"kid\": \"kid\"\n" + + "}"; + + @Test + public void shouldDeserialize() throws Exception { + EncryptionKey key = fromJSON(json, EncryptionKey.class); + + assertThat(key, is(notNullValue())); + assertThat(key.getKid(), is("kid")); + assertThat(key.getType(), is("tenant-master-key")); + assertThat(key.getState(), is("active")); + assertThat(key.getCreatedAt(), is("2024-10-16T10:50:44.107Z")); + assertThat(key.getUpdatedAt(), is("2024-10-24T06:47:24.899Z")); + assertThat(key.getParentKid(), is("pkid")); + assertThat(key.getPublicKey(), is("pkey")); + } + + @Test + public void shouldSerialize() throws Exception { + EncryptionKey key = new EncryptionKey(); + key.setKid("kid"); + key.setType("tenant-master-key"); + key.setState("active"); + key.setCreatedAt("2024-10-16T10:50:44.107Z"); + key.setUpdatedAt("2024-10-24T06:47:24.899Z"); + key.setParentKid("pkid"); + key.setPublicKey("pkey"); + + String serialized = toJSON(key); + assertThat(serialized, is(notNullValue())); + assertThat(serialized, JsonMatcher.hasEntry("kid", "kid")); + assertThat(serialized, JsonMatcher.hasEntry("type", "tenant-master-key")); + assertThat(serialized, JsonMatcher.hasEntry("state", "active")); + assertThat(serialized, JsonMatcher.hasEntry("created_at", "2024-10-16T10:50:44.107Z")); + assertThat(serialized, JsonMatcher.hasEntry("updated_at", "2024-10-24T06:47:24.899Z")); + assertThat(serialized, JsonMatcher.hasEntry("parent_kid", "pkid")); + assertThat(serialized, JsonMatcher.hasEntry("public_key", "pkey")); + } + + @Test + public void shouldIncludeReadOnlyValuesOnDeserialize() throws Exception { + EncryptionKey key = fromJSON(readOnlyJson, EncryptionKey.class); + + assertThat(key, is(notNullValue())); + assertThat(key.getKid(), is("kid")); + } +} diff --git a/src/test/java/com/auth0/json/mgmt/keys/EncryptionKeysPageTest.java b/src/test/java/com/auth0/json/mgmt/keys/EncryptionKeysPageTest.java new file mode 100644 index 000000000..07ed0935f --- /dev/null +++ b/src/test/java/com/auth0/json/mgmt/keys/EncryptionKeysPageTest.java @@ -0,0 +1,94 @@ +package com.auth0.json.mgmt.keys; + +import com.auth0.json.JsonTest; +import org.junit.jupiter.api.Test; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; + +public class EncryptionKeysPageTest extends JsonTest { + + private static final String jsonWithTotal = "{\n" + + " \"start\": 0,\n" + + " \"total\": 20,\n" + + " \"limit\": 50,\n" + + " \"keys\": [\n" + + " {\n" + + " \"kid\": \"kid-1\",\n" + + " \"type\": \"customer-provided-root-key\",\n" + + " \"state\": \"pre-activation\",\n" + + " \"created_at\": \"2024-10-24T08:02:18.029Z\",\n" + + " \"updated_at\": \"2024-10-24T08:02:18.029Z\",\n" + + " \"parent_kid\": null,\n" + + " \"public_key\": null\n" + + " },\n" + + " {\n" + + " \"kid\": \"kid-2\",\n" + + " \"type\": \"tenant-master-key\",\n" + + " \"state\": \"active\",\n" + + " \"created_at\": \"2024-10-24T06:47:23.749Z\",\n" + + " \"updated_at\": \"2024-10-24T06:47:23.749Z\",\n" + + " \"parent_kid\": \"pkid-1\",\n" + + " \"public_key\": null\n" + + " }\n" + + " ]\n" + + "}"; + + private static final String jsonWithoutTotal = "{\n" + + " \"start\": 0,\n" + + " \"limit\": 50,\n" + + " \"keys\": [\n" + + " {\n" + + " \"kid\": \"kid-1\",\n" + + " \"type\": \"customer-provided-root-key\",\n" + + " \"state\": \"pre-activation\",\n" + + " \"created_at\": \"2024-10-24T08:02:18.029Z\",\n" + + " \"updated_at\": \"2024-10-24T08:02:18.029Z\",\n" + + " \"parent_kid\": null,\n" + + " \"public_key\": null\n" + + " },\n" + + " {\n" + + " \"kid\": \"kid-2\",\n" + + " \"type\": \"tenant-master-key\",\n" + + " \"state\": \"active\",\n" + + " \"created_at\": \"2024-10-24T06:47:23.749Z\",\n" + + " \"updated_at\": \"2024-10-24T06:47:23.749Z\",\n" + + " \"parent_kid\": \"pkid-1\",\n" + + " \"public_key\": null\n" + + " }\n" + + " ]\n" + + "}"; + + @Test + public void shouldDeserializeWithTotal() throws Exception { + EncryptionKeysPage page = fromJSON(jsonWithTotal, EncryptionKeysPage.class); + + assertThat(page, is(notNullValue())); + assertThat(page.getStart(), is(0)); + assertThat(page.getTotal(), is(20)); + assertThat(page.getLimit(), is(50)); + assertThat(page.getItems(), is(notNullValue())); + assertThat(page.getItems().size(), is(2)); + assertThat(page.getItems().get(0).getKid(), is("kid-1")); + assertThat(page.getItems().get(0).getType(), is("customer-provided-root-key")); + assertThat(page.getItems().get(0).getState(), is("pre-activation")); + assertThat(page.getItems().get(0).getCreatedAt(), is("2024-10-24T08:02:18.029Z")); + assertThat(page.getItems().get(0).getUpdatedAt(), is("2024-10-24T08:02:18.029Z")); + } + + @Test + public void shouldDeserializeWithoutTotal() throws Exception { + EncryptionKeysPage page = fromJSON(jsonWithoutTotal, EncryptionKeysPage.class); + + assertThat(page, is(notNullValue())); + assertThat(page.getStart(), is(0)); + assertThat(page.getLimit(), is(50)); + assertThat(page.getItems(), is(notNullValue())); + assertThat(page.getItems().size(), is(2)); + assertThat(page.getItems().get(0).getKid(), is("kid-1")); + assertThat(page.getItems().get(0).getType(), is("customer-provided-root-key")); + assertThat(page.getItems().get(0).getState(), is("pre-activation")); + assertThat(page.getItems().get(0).getCreatedAt(), is("2024-10-24T08:02:18.029Z")); + assertThat(page.getItems().get(0).getUpdatedAt(), is("2024-10-24T08:02:18.029Z")); + } +} diff --git a/src/test/java/com/auth0/json/mgmt/keys/EncryptionWrappingKeyResponseTest.java b/src/test/java/com/auth0/json/mgmt/keys/EncryptionWrappingKeyResponseTest.java new file mode 100644 index 000000000..c6762702c --- /dev/null +++ b/src/test/java/com/auth0/json/mgmt/keys/EncryptionWrappingKeyResponseTest.java @@ -0,0 +1,49 @@ +package com.auth0.json.mgmt.keys; + +import com.auth0.json.JsonMatcher; +import com.auth0.json.JsonTest; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; + +public class EncryptionWrappingKeyResponseTest extends JsonTest { + private static final String json = "{\n" + + " \"public_key\": \"pkey\",\n" + + " \"algorithm\": \"alg\"\n" + + "}"; + + private static final String readOnlyJson = "{\n" + + " \"public_key\": \"pkey\"\n" + + "}"; + + @Test + public void shouldDeserialize() throws Exception { + EncryptionWrappingKeyResponse response = fromJSON(json, EncryptionWrappingKeyResponse.class); + + assertThat(response, is(notNullValue())); + assertThat(response.getPublicKey(), is("pkey")); + assertThat(response.getAlgorithm(), is("alg")); + } + + @Test + public void shouldSerialize() throws Exception { + EncryptionWrappingKeyResponse response = new EncryptionWrappingKeyResponse(); + response.setPublicKey("pkey"); + response.setAlgorithm("alg"); + + String serialized = toJSON(response); + assertThat(serialized, is(notNullValue())); + assertThat(serialized, JsonMatcher.hasEntry("public_key", "pkey")); + assertThat(serialized, JsonMatcher.hasEntry("algorithm", "alg")); + } + + @Test + public void shouldIncludeReadOnlyValuesOnDeserialize() throws Exception { + EncryptionWrappingKeyResponse response = fromJSON(readOnlyJson, EncryptionWrappingKeyResponse.class); + + assertThat(response, is(notNullValue())); + assertThat(response.getPublicKey(), is("pkey")); + } +} diff --git a/src/test/java/com/auth0/json/mgmt/KeyTest.java b/src/test/java/com/auth0/json/mgmt/keys/KeyTest.java similarity index 97% rename from src/test/java/com/auth0/json/mgmt/KeyTest.java rename to src/test/java/com/auth0/json/mgmt/keys/KeyTest.java index 9f63864b0..1f69edb0c 100644 --- a/src/test/java/com/auth0/json/mgmt/KeyTest.java +++ b/src/test/java/com/auth0/json/mgmt/keys/KeyTest.java @@ -1,9 +1,8 @@ -package com.auth0.json.mgmt; +package com.auth0.json.mgmt.keys; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; -import java.text.DateFormat; import java.time.Instant; import java.util.Date; diff --git a/src/test/java/com/auth0/json/mgmt/logevents/LogEventTest.java b/src/test/java/com/auth0/json/mgmt/logevents/LogEventTest.java index 0aaa68d98..fafcf175c 100644 --- a/src/test/java/com/auth0/json/mgmt/logevents/LogEventTest.java +++ b/src/test/java/com/auth0/json/mgmt/logevents/LogEventTest.java @@ -1,7 +1,9 @@ package com.auth0.json.mgmt.logevents; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; @@ -9,7 +11,34 @@ public class LogEventTest extends JsonTest { - private static final String json = "{\"_id\":\"123\", \"log_id\":\"123\", \"date\":\"2016-02-23T19:57:29.532Z\",\"type\":\"thetype\",\"location_info\":{},\"details\":{},\"client_id\":\"clientId\",\"client_name\":\"clientName\",\"ip\":\"233.233.233.11\",\"user_id\":\"userId\",\"user_name\":\"userName\"}"; + private static final String json = "{\n" + + " \"_id\": \"123\",\n" + + " \"log_id\": \"123\",\n" + + " \"date\": \"2016-02-23T19:57:29.532Z\",\n" + + " \"type\": \"thetype\",\n" + + " \"location_info\": {},\n" + + " \"details\": {},\n" + + " \"client_id\": \"clientId\",\n" + + " \"client_name\": \"clientName\",\n" + + " \"ip\": \"233.233.233.11\",\n" + + " \"user_id\": \"userId\",\n" + + " \"user_name\": \"userName\",\n" + + " \"connection\": \"connection\",\n" + + " \"connection_id\": \"connectionId\",\n" + + " \"description\": \"description\",\n" + + " \"hostname\": \"hostname\",\n" + + " \"audience\": \"audience\",\n" + + " \"organization_id\": \"org_1\",\n" + + " \"organization_name\": \"org2\",\n" + + " \"$event_schema\": {\n" + + " \"version\": \"1.0.0\"\n" + + " },\n" + + " \"tenant_name\": \"paid-testing\",\n" + + " \"audience\": \"audience\",\n" + + " \"isMobile\": \"false\",\n" + + " \"user_agent\": \"okhttp 4.11.0 / Other 0.0.0\",\n" + + " \"scope\": [\"read:client_grants\", \"create:client_grants\"]\n" + + "}"; @Test public void shouldDeserialize() throws Exception { @@ -27,5 +56,17 @@ public void shouldDeserialize() throws Exception { assertThat(logEvent.getUserName(), is("userName")); assertThat(logEvent.getLocationInfo(), is(notNullValue())); assertThat(logEvent.getDetails(), is(notNullValue())); + assertThat(logEvent.getAudience(), is("audience")); + assertThat(logEvent.getConnection(), is("connection")); + assertThat(logEvent.getConnectionId(), is("connectionId")); + assertThat(logEvent.getHostname(), is("hostname")); + assertThat(logEvent.getDescription(), is("description")); + assertThat(logEvent.isMobile(), is(false)); + assertThat(logEvent.getUserAgent(), is("okhttp 4.11.0 / Other 0.0.0")); + assertThat(logEvent.getOrganizationId(), is("org_1")); + assertThat(logEvent.getOrganizationName(), is("org2")); + assertThat(logEvent.getTenantName(), is("paid-testing")); + assertThat(logEvent.getEventSchema(), is(notNullValue())); + assertThat(logEvent.getScope(), is(Arrays.asList("read:client_grants", "create:client_grants"))); } } diff --git a/src/test/java/com/auth0/json/mgmt/logevents/LogEventsPageTest.java b/src/test/java/com/auth0/json/mgmt/logevents/LogEventsPageTest.java index 759097bf3..b0856f350 100644 --- a/src/test/java/com/auth0/json/mgmt/logevents/LogEventsPageTest.java +++ b/src/test/java/com/auth0/json/mgmt/logevents/LogEventsPageTest.java @@ -1,7 +1,7 @@ package com.auth0.json.mgmt.logevents; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; @@ -36,4 +36,4 @@ public void shouldDeserializeWithTotals() throws Exception { assertThat(page.getItems().size(), is(1)); } -} \ No newline at end of file +} diff --git a/src/test/java/com/auth0/json/mgmt/logstreams/LogStreamsTest.java b/src/test/java/com/auth0/json/mgmt/logstreams/LogStreamsTest.java index ca709aa0a..c02402609 100644 --- a/src/test/java/com/auth0/json/mgmt/logstreams/LogStreamsTest.java +++ b/src/test/java/com/auth0/json/mgmt/logstreams/LogStreamsTest.java @@ -2,7 +2,7 @@ import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.Arrays; import java.util.Collections; diff --git a/src/test/java/com/auth0/json/mgmt/networkacls/NetworkAclsPageTest.java b/src/test/java/com/auth0/json/mgmt/networkacls/NetworkAclsPageTest.java new file mode 100644 index 000000000..ed39d9156 --- /dev/null +++ b/src/test/java/com/auth0/json/mgmt/networkacls/NetworkAclsPageTest.java @@ -0,0 +1,115 @@ +package com.auth0.json.mgmt.networkacls; + +import com.auth0.json.JsonTest; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; + +public class NetworkAclsPageTest extends JsonTest { + + private static final String jsonWithTotal = "{\n" + + " \"total\": 2,\n" + + " \"start\": 0,\n" + + " \"limit\": 2,\n" + + " \"network_acls\": [\n" + + " {\n" + + " \"description\": \"Log America and Canada all the time.\",\n" + + " \"active\": true,\n" + + " \"priority\": 1,\n" + + " \"rule\": {\n" + + " \"match\": {\n" + + " \"geo_country_codes\": [\n" + + " \"US\",\n" + + " \"CA\"\n" + + " ]\n" + + " },\n" + + " \"scope\": \"authentication\",\n" + + " \"action\": {\n" + + " \"log\": true\n" + + " }\n" + + " },\n" + + " \"created_at\": \"2025-03-17T12:31:57.782Z\",\n" + + " \"updated_at\": \"2025-03-17T12:31:57.782Z\",\n" + + " \"id\": \"acl_1\"\n" + + " },\n" + + " {\n" + + " \"description\": \"Test Desc - 1\",\n" + + " \"active\": true,\n" + + " \"priority\": 10,\n" + + " \"rule\": {\n" + + " \"match\": {\n" + + " \"ipv4_cidrs\": [\n" + + " \"198.0.0.0\",\n" + + " \"10.0.0.0/24\"\n" + + " ]\n" + + " },\n" + + " \"scope\": \"management\",\n" + + " \"action\": {\n" + + " \"block\": true\n" + + " }\n" + + " },\n" + + " \"created_at\": \"2025-06-10T06:18:10.277Z\",\n" + + " \"updated_at\": \"2025-06-10T06:18:10.277Z\",\n" + + " \"id\": \"acl_2\"\n" + + " }\n" + + " ]\n" + + "}"; + + private static final String jsonWithoutTotal = "[\n" + + " {\n" + + " \"description\": \"Test Desc - 1\",\n" + + " \"active\": true,\n" + + " \"priority\": 10,\n" + + " \"rule\": {\n" + + " \"match\": {\n" + + " \"ipv4_cidrs\": [\n" + + " \"198.0.0.0\",\n" + + " \"10.0.0.0/24\"\n" + + " ]\n" + + " },\n" + + " \"scope\": \"management\",\n" + + " \"action\": {\n" + + " \"block\": true\n" + + " }\n" + + " },\n" + + " \"created_at\": \"2025-06-10T06:18:10.277Z\",\n" + + " \"updated_at\": \"2025-06-10T06:18:10.277Z\",\n" + + " \"id\": \"acl_1\"\n" + + " }\n" + + "]"; + + @Test + public void shouldDeserializeWithTotal() throws Exception { + NetworkAclsPage page = fromJSON(jsonWithTotal, NetworkAclsPage.class); + + assertThat(page, is(notNullValue())); + assertThat(page.getStart(), is(0)); + assertThat(page.getTotal(), is(2)); + assertThat(page.getLimit(), is(2)); + assertThat(page.getItems(), is(notNullValue())); + assertThat(page.getItems().size(), is(2)); + assertThat(page.getItems().get(0).getDescription(), is("Log America and Canada all the time.")); + assertThat(page.getItems().get(0).isActive(), is(true)); + assertThat(page.getItems().get(0).getPriority(), is(1)); + assertThat(page.getItems().get(0).getId(), is("acl_1")); + assertThat(page.getItems().get(0).getCreatedAt(), is("2025-03-17T12:31:57.782Z")); + assertThat(page.getItems().get(0).getUpdatedAt(), is("2025-03-17T12:31:57.782Z")); + } + + @Test + public void shouldDeserializeWithoutTotal() throws Exception { + NetworkAclsPage page = fromJSON(jsonWithoutTotal, NetworkAclsPage.class); + + assertThat(page, is(notNullValue())); + assertThat(page.getItems(), is(notNullValue())); + assertThat(page.getItems().size(), is(1)); + assertThat(page.getItems().get(0).getDescription(), is("Test Desc - 1")); + assertThat(page.getItems().get(0).isActive(), is(true)); + assertThat(page.getItems().get(0).getPriority(), is(10)); + assertThat(page.getItems().get(0).getId(), is("acl_1")); + assertThat(page.getItems().get(0).getCreatedAt(), is("2025-06-10T06:18:10.277Z")); + assertThat(page.getItems().get(0).getUpdatedAt(), is("2025-06-10T06:18:10.277Z")); + } +} diff --git a/src/test/java/com/auth0/json/mgmt/networkacls/NetworkAclsTest.java b/src/test/java/com/auth0/json/mgmt/networkacls/NetworkAclsTest.java new file mode 100644 index 000000000..5b7abb9dd --- /dev/null +++ b/src/test/java/com/auth0/json/mgmt/networkacls/NetworkAclsTest.java @@ -0,0 +1,54 @@ +package com.auth0.json.mgmt.networkacls; + +import com.auth0.json.JsonTest; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; + +import static com.auth0.json.JsonMatcher.hasEntry; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; + +public class NetworkAclsTest extends JsonTest { + + private final static String NETWORK_ACLS_JSON = "src/test/resources/mgmt/network_acls.json"; + + @Test + public void deserialize() throws Exception { + NetworkAcls deserialized = fromJSON(readTextFile(NETWORK_ACLS_JSON), NetworkAcls.class); + + assertThat(deserialized.getDescription(), is("Log America and Canada all the time.")); + assertThat(deserialized.isActive(), is(true)); + assertThat(deserialized.getPriority(), is(1)); + assertThat(deserialized.getId(), is("acl_1")); + assertThat(deserialized.getCreatedAt(), is("2025-03-17T12:31:57.782Z")); + assertThat(deserialized.getUpdatedAt(), is("2025-03-17T12:31:57.782Z")); + } + + @Test + public void serialize() throws Exception { + NetworkAcls networkAcls = new NetworkAcls(); + networkAcls.setDescription("Log America and Canada all the time."); + networkAcls.setActive(true); + networkAcls.setPriority(1); + + Rule rule = new Rule(); + Match match = new Match(); + match.setGeoCountryCodes(Arrays.asList("US", "CA")); + rule.setMatch(match); + rule.setScope("authentication"); + Action action = new Action(); + action.setLog(true); + rule.setAction(action); + + networkAcls.setRule(rule); + + String json = toJSON(networkAcls); + + assertThat(json, hasEntry("description", "Log America and Canada all the time.")); + assertThat(json, hasEntry("active", true)); + assertThat(json, hasEntry("priority", 1)); + assertThat(json, hasEntry("rule", notNullValue())); + } +} diff --git a/src/test/java/com/auth0/json/mgmt/organizations/EnabledConnectionsPageTest.java b/src/test/java/com/auth0/json/mgmt/organizations/EnabledConnectionsPageTest.java index ad3c92524..8bfe75295 100644 --- a/src/test/java/com/auth0/json/mgmt/organizations/EnabledConnectionsPageTest.java +++ b/src/test/java/com/auth0/json/mgmt/organizations/EnabledConnectionsPageTest.java @@ -1,7 +1,7 @@ package com.auth0.json.mgmt.organizations; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; @@ -12,6 +12,7 @@ public class EnabledConnectionsPageTest extends JsonTest " {\n" + " \"connection_id\": \"con_1\",\n" + " \"assign_membership_on_login\": false,\n" + + " \"is_signup_enabled\": true,\n" + " \"connection\": {\n" + " \"name\": \"google-oauth2\",\n" + " \"strategy\": \"google-oauth2\"\n" + @@ -20,6 +21,7 @@ public class EnabledConnectionsPageTest extends JsonTest " {\n" + " \"connection_id\": \"con_2\",\n" + " \"assign_membership_on_login\": true,\n" + + " \"is_signup_enabled\": true,\n" + " \"connection\": {\n" + " \"name\": \"Username-Password-Authentication\",\n" + " \"strategy\": \"auth0\"\n" + @@ -32,6 +34,7 @@ public class EnabledConnectionsPageTest extends JsonTest " {\n" + " \"connection_id\": \"con_1\",\n" + " \"assign_membership_on_login\": false,\n" + + " \"is_signup_enabled\": true,\n" + " \"connection\": {\n" + " \"name\": \"google-oauth2\",\n" + " \"strategy\": \"google-oauth2\"\n" + @@ -40,6 +43,7 @@ public class EnabledConnectionsPageTest extends JsonTest " {\n" + " \"connection_id\": \"con_2\",\n" + " \"assign_membership_on_login\": true,\n" + + " \"is_signup_enabled\": true,\n" + " \"connection\": {\n" + " \"name\": \"Username-Password-Authentication\",\n" + " \"strategy\": \"auth0\"\n" + diff --git a/src/test/java/com/auth0/json/mgmt/organizations/EnabledConnectionsTest.java b/src/test/java/com/auth0/json/mgmt/organizations/EnabledConnectionsTest.java index e45d085b7..49017692d 100644 --- a/src/test/java/com/auth0/json/mgmt/organizations/EnabledConnectionsTest.java +++ b/src/test/java/com/auth0/json/mgmt/organizations/EnabledConnectionsTest.java @@ -2,13 +2,14 @@ import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.HashMap; import java.util.Map; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; public class EnabledConnectionsTest extends JsonTest { @@ -21,6 +22,7 @@ public void shouldSerialize() throws Exception { EnabledConnection enabledConnection = new EnabledConnection(); enabledConnection.setAssignMembershipOnLogin(true); enabledConnection.setConnection(connection); + enabledConnection.setSignupEnabled(true); String serialized = toJSON(enabledConnection); assertThat(serialized, is(notNullValue())); @@ -38,6 +40,7 @@ public void shouldDeserialize() throws Exception { String json = "{\n" + " \"connection_id\": \"con_id\",\n" + " \"assign_membership_on_login\": false,\n" + + " \"is_signup_enabled\": true,\n" + " \"connection\": {\n" + " \"name\": \"google-oauth2\",\n" + " \"strategy\": \"google-oauth2\"\n" + @@ -48,6 +51,7 @@ public void shouldDeserialize() throws Exception { assertThat(enabledConnection, is(notNullValue())); assertThat(enabledConnection.getConnectionId(), is("con_id")); assertThat(enabledConnection.isAssignMembershipOnLogin(), is(false)); + assertThat(enabledConnection.getSignupEnabled(), is(true)); assertThat(enabledConnection.getConnection(), is(notNullValue())); assertThat(enabledConnection.getConnection().getName(), is("google-oauth2")); assertThat(enabledConnection.getConnection().getStrategy(), is("google-oauth2")); diff --git a/src/test/java/com/auth0/json/mgmt/organizations/InvitationTest.java b/src/test/java/com/auth0/json/mgmt/organizations/InvitationTest.java index ed85daba2..ad4a60864 100644 --- a/src/test/java/com/auth0/json/mgmt/organizations/InvitationTest.java +++ b/src/test/java/com/auth0/json/mgmt/organizations/InvitationTest.java @@ -2,7 +2,7 @@ import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.Arrays; import java.util.Collections; diff --git a/src/test/java/com/auth0/json/mgmt/organizations/InvitationsPageTest.java b/src/test/java/com/auth0/json/mgmt/organizations/InvitationsPageTest.java index ccb8534a0..4ec1e27c3 100644 --- a/src/test/java/com/auth0/json/mgmt/organizations/InvitationsPageTest.java +++ b/src/test/java/com/auth0/json/mgmt/organizations/InvitationsPageTest.java @@ -1,11 +1,10 @@ package com.auth0.json.mgmt.organizations; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; -import static org.hamcrest.Matchers.is; public class InvitationsPageTest extends JsonTest { diff --git a/src/test/java/com/auth0/json/mgmt/organizations/MembersPageTest.java b/src/test/java/com/auth0/json/mgmt/organizations/MembersPageTest.java index 34168f522..5308e132e 100644 --- a/src/test/java/com/auth0/json/mgmt/organizations/MembersPageTest.java +++ b/src/test/java/com/auth0/json/mgmt/organizations/MembersPageTest.java @@ -1,7 +1,7 @@ package com.auth0.json.mgmt.organizations; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.ArrayList; diff --git a/src/test/java/com/auth0/json/mgmt/organizations/MembersTest.java b/src/test/java/com/auth0/json/mgmt/organizations/MembersTest.java index 7ae6f8807..a70c7e350 100644 --- a/src/test/java/com/auth0/json/mgmt/organizations/MembersTest.java +++ b/src/test/java/com/auth0/json/mgmt/organizations/MembersTest.java @@ -2,10 +2,11 @@ import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; public class MembersTest extends JsonTest { @@ -29,7 +30,13 @@ public void shouldDeserialize() throws Exception { " \"user_id\": \"user_123\",\n" + " \"email\": \"fred@domain.com\",\n" + " \"picture\": \"https://profilepic.com/mypic.png\",\n" + - " \"name\": \"fred\"\n" + + " \"name\": \"fred\",\n" + + " \"roles\": [\n" + + " {\n" + + " \"id\": \"rol_abc\",\n" + + " \"name\": \"test role\"\n" + + " }\n" + + " ]" + "}"; Member member = fromJSON(memberJson, Member.class); @@ -38,6 +45,8 @@ public void shouldDeserialize() throws Exception { assertThat(member.getEmail(), is("fred@domain.com")); assertThat(member.getPicture(), is("https://profilepic.com/mypic.png")); assertThat(member.getName(), is("fred")); - + assertThat(member.getRoles().size(), is(1)); + assertThat(member.getRoles().get(0).getName(), is("test role")); + assertThat(member.getRoles().get(0).getId(), is("rol_abc")); } } diff --git a/src/test/java/com/auth0/json/mgmt/organizations/OrganizationClientGrantTest.java b/src/test/java/com/auth0/json/mgmt/organizations/OrganizationClientGrantTest.java new file mode 100644 index 000000000..5d44821f0 --- /dev/null +++ b/src/test/java/com/auth0/json/mgmt/organizations/OrganizationClientGrantTest.java @@ -0,0 +1,48 @@ +package com.auth0.json.mgmt.organizations; + +import com.auth0.json.JsonMatcher; +import com.auth0.json.JsonTest; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; + +public class OrganizationClientGrantTest extends JsonTest { + + @Test + public void shouldSerialize() throws Exception { + OrganizationClientGrant clientGrant = new OrganizationClientGrant(); + clientGrant.setClientId("client-id"); + clientGrant.setAudience("https://api-identifier/"); + clientGrant.setScope(Arrays.asList("read:messages", "write:messages")); + + String serialized = toJSON(clientGrant); + assertThat(serialized, is(notNullValue())); + assertThat(serialized, JsonMatcher.hasEntry("client_id", "client-id")); + assertThat(serialized, JsonMatcher.hasEntry("audience", "https://api-identifier/")); + assertThat(serialized, JsonMatcher.hasEntry("scope", Arrays.asList("read:messages", "write:messages"))); + } + + @Test + public void shouldDeserialize() throws Exception { + String json = "{\n" + + " \"id\": \"1\",\n" + + " \"client_id\": \"clientId1\",\n" + + " \"audience\": \"audience1\",\n" + + " \"scope\": [\n" + + " \"openid\",\n" + + " \"profile\"\n" + + " ]\n" + + "}"; + + OrganizationClientGrant clientGrant = fromJSON(json, OrganizationClientGrant.class); + + assertThat(clientGrant, is(notNullValue())); + + assertThat(clientGrant.getAudience(), is("audience1")); + assertThat(clientGrant.getClientId(), is("clientId1")); + assertThat(clientGrant.getScope(), contains("openid", "profile")); + } +} diff --git a/src/test/java/com/auth0/json/mgmt/organizations/OrganizationClientGrantsPageTest.java b/src/test/java/com/auth0/json/mgmt/organizations/OrganizationClientGrantsPageTest.java new file mode 100644 index 000000000..89aa3fe9f --- /dev/null +++ b/src/test/java/com/auth0/json/mgmt/organizations/OrganizationClientGrantsPageTest.java @@ -0,0 +1,71 @@ +package com.auth0.json.mgmt.organizations; + +import com.auth0.json.JsonTest; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; + +public class OrganizationClientGrantsPageTest extends JsonTest { + + private static final String JSON_WITHOUT_TOTALS = "[\n" + + " {\n" + + " \"id\": \"cgr_4pI9a42haOLLWnwq\",\n" + + " \"client_id\": \"client-id\",\n" + + " \"audience\": \"https://api-identifier\",\n" + + " \"scope\": [\n" + + " \"update:items\",\n" + + " \"read:messages\"\n" + + " ]\n" + + " },\n" + + " {\n" + + " \"id\": \"cgr_D018f9kmBmwbZod\",\n" + + " \"client_id\": \"client-id\",\n" + + " \"audience\": \"https://api-identifier\",\n" + + " \"scope\": []\n" + + " }\n" + + "]"; + + private static final String JSON_WITH_TOTALS = "{\n" + + " \"total\": 13,\n" + + " \"start\": 0,\n" + + " \"limit\": 1,\n" + + " \"client_grants\": [\n" + + " {\n" + + " \"id\": \"cgr_3aidkk3skLVOM3Ay7\",\n" + + " \"client_id\": \"client-id\",\n" + + " \"audience\": \"https://api-identifier/\",\n" + + " \"scope\": [\n" + + " \"read:messages\"\n" + + " ]\n" + + " }\n" + + " ]\n" + + "}"; + + @Test + public void shouldDeserializeWithoutTotals() throws Exception { + OrganizationClientGrantsPage page = fromJSON(JSON_WITHOUT_TOTALS, OrganizationClientGrantsPage.class); + + assertThat(page, is(notNullValue())); + assertThat(page.getStart(), is(nullValue())); + assertThat(page.getLength(), is(nullValue())); + assertThat(page.getTotal(), is(nullValue())); + assertThat(page.getLimit(), is(nullValue())); + assertThat(page.getNext(), is(nullValue())); + assertThat(page.getItems(), is(notNullValue())); + assertThat(page.getItems().size(), is(2)); + } + + @Test + public void shouldDeserializeWithTotals() throws Exception { + OrganizationClientGrantsPage page = fromJSON(JSON_WITH_TOTALS, OrganizationClientGrantsPage.class); + + assertThat(page, is(notNullValue())); + assertThat(page.getStart(), is(0)); + assertThat(page.getTotal(), is(13)); + assertThat(page.getLimit(), is(1)); + assertThat(page.getNext(), is(nullValue())); + assertThat(page.getItems(), is(notNullValue())); + assertThat(page.getItems().size(), is(1)); + } +} diff --git a/src/test/java/com/auth0/json/mgmt/organizations/OrganizationsPageTest.java b/src/test/java/com/auth0/json/mgmt/organizations/OrganizationsPageTest.java index b681bfb94..db9a5f8bb 100644 --- a/src/test/java/com/auth0/json/mgmt/organizations/OrganizationsPageTest.java +++ b/src/test/java/com/auth0/json/mgmt/organizations/OrganizationsPageTest.java @@ -1,7 +1,7 @@ package com.auth0.json.mgmt.organizations; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.ArrayList; diff --git a/src/test/java/com/auth0/json/mgmt/organizations/OrganizationsTest.java b/src/test/java/com/auth0/json/mgmt/organizations/OrganizationsTest.java index 395153677..ea5cdd22f 100644 --- a/src/test/java/com/auth0/json/mgmt/organizations/OrganizationsTest.java +++ b/src/test/java/com/auth0/json/mgmt/organizations/OrganizationsTest.java @@ -2,7 +2,9 @@ import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; -import org.junit.Test; +import com.auth0.json.mgmt.tokenquota.ClientCredentials; +import com.auth0.json.mgmt.tokenquota.TokenQuota; +import org.junit.jupiter.api.Test; import java.util.ArrayList; import java.util.Collections; @@ -10,33 +12,35 @@ import java.util.Map; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; public class OrganizationsTest extends JsonTest { @Test public void shouldDeserialize() throws Exception { String orgJson = "{\n" + - " \"id\": \"org_abc\",\n" + - " \"name\": \"org-name\",\n" + - " \"display_name\": \"display name\",\n" + - " \"branding\": {\n" + - " \"logo_url\": \"https://some-url.com/\",\n" + - " \"colors\": {\n" + - " \"primary\": \"#FF0000\",\n" + - " \"page_background\": \"#FF0000\"\n" + - " }\n" + - " },\n" + - " \"metadata\": {\n" + - " \"key1\": \"val1\"\n" + - " },\n" + - " \"enabled_connections\": [\n" + - " {\n" + - " \"connection_id\": \"con-1\",\n" + - " \"assign_membership_on_login\": \"false\"\n" + - " }\n" + - " ]\n" + - " }"; + " \"id\": \"org_abc\",\n" + + " \"name\": \"org-name\",\n" + + " \"display_name\": \"display name\",\n" + + " \"branding\": {\n" + + " \"logo_url\": \"https://some-url.com/\",\n" + + " \"colors\": {\n" + + " \"primary\": \"#FF0000\",\n" + + " \"page_background\": \"#FF0000\"\n" + + " }\n" + + " },\n" + + " \"metadata\": {\n" + + " \"key1\": \"val1\"\n" + + " },\n" + + " \"token_quota\": {\n" + + " \"client_credentials\": {\n" + + " \"per_hour\": 10,\n" + + " \"per_day\": 100,\n" + + " \"enforce\": true\n" + + " }\n" + + " }\n" + + "}"; Organization org = fromJSON(orgJson, Organization.class); assertThat(org, is(notNullValue())); @@ -50,8 +54,11 @@ public void shouldDeserialize() throws Exception { assertThat(org.getBranding().getColors().getPageBackground(), is("#FF0000")); assertThat(org.getMetadata(), is(notNullValue())); assertThat(org.getMetadata().get("key1"), is("val1")); - assertThat(org.getEnabledConnections().get(0).getConnectionId(), is("con-1")); - assertThat(org.getEnabledConnections().get(0).isAssignMembershipOnLogin(), is(false)); + assertThat(org.getTokenQuota(), is(notNullValue())); + assertThat(org.getTokenQuota().getClientCredentials(), is(notNullValue())); + assertThat(org.getTokenQuota().getClientCredentials().getPerHour(), is(10)); + assertThat(org.getTokenQuota().getClientCredentials().getPerDay(), is(100)); + assertThat(org.getTokenQuota().getClientCredentials().isEnforce(), is(true)); } @Test @@ -77,6 +84,9 @@ public void shouldSerialize() throws Exception { enabledConnections.add(enabledConnection); organization.setEnabledConnections(enabledConnections); + TokenQuota tokenQuota = new TokenQuota(new ClientCredentials(100, 10, true)); + organization.setTokenQuota(tokenQuota); + String serialized = toJSON(organization); assertThat(serialized, is(notNullValue())); assertThat(serialized, JsonMatcher.hasEntry("name", "org-name")); @@ -84,5 +94,14 @@ public void shouldSerialize() throws Exception { assertThat(serialized, JsonMatcher.hasEntry("metadata", metadata)); assertThat(serialized, JsonMatcher.hasEntry("enabled_connections", is(notNullValue()))); assertThat(serialized, JsonMatcher.hasEntry("branding", is(notNullValue()))); + assertThat(serialized, JsonMatcher.hasEntry("branding", JsonMatcher.hasEntry("logo_url", "https://some-url.com"))); + assertThat(serialized, JsonMatcher.hasEntry("branding", JsonMatcher.hasEntry("colors", is(notNullValue())))); + assertThat(serialized, JsonMatcher.hasEntry("branding", JsonMatcher.hasEntry("colors", JsonMatcher.hasEntry("primary", "#FF0000")))); + assertThat(serialized, JsonMatcher.hasEntry("branding", JsonMatcher.hasEntry("colors", JsonMatcher.hasEntry("page_background", "#DD0000")))); + assertThat(serialized, JsonMatcher.hasEntry("token_quota", is(notNullValue()))); + assertThat(serialized, JsonMatcher.hasEntry("token_quota", JsonMatcher.hasEntry("client_credentials", is(notNullValue())))); + assertThat(serialized, JsonMatcher.hasEntry("token_quota", JsonMatcher.hasEntry("client_credentials", JsonMatcher.hasEntry("per_hour", 10)))); + assertThat(serialized, JsonMatcher.hasEntry("token_quota", JsonMatcher.hasEntry("client_credentials", JsonMatcher.hasEntry("per_day", 100)))); + assertThat(serialized, JsonMatcher.hasEntry("token_quota", JsonMatcher.hasEntry("client_credentials", JsonMatcher.hasEntry("enforce", true)))); } } diff --git a/src/test/java/com/auth0/json/mgmt/permissions/PermissionSourceTest.java b/src/test/java/com/auth0/json/mgmt/permissions/PermissionSourceTest.java index 6e9fa0c25..d837a2f09 100644 --- a/src/test/java/com/auth0/json/mgmt/permissions/PermissionSourceTest.java +++ b/src/test/java/com/auth0/json/mgmt/permissions/PermissionSourceTest.java @@ -1,8 +1,7 @@ package com.auth0.json.mgmt.permissions; import com.auth0.json.JsonTest; -import com.auth0.json.mgmt.PermissionSource; -import org.junit.Test; +import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; @@ -22,4 +21,4 @@ public void shouldDeserialize() throws Exception { assertThat(permission.getType(), is("sType")); } -} \ No newline at end of file +} diff --git a/src/test/java/com/auth0/json/mgmt/permissions/PermissionTest.java b/src/test/java/com/auth0/json/mgmt/permissions/PermissionTest.java index 2dc965ec9..9be0a044e 100644 --- a/src/test/java/com/auth0/json/mgmt/permissions/PermissionTest.java +++ b/src/test/java/com/auth0/json/mgmt/permissions/PermissionTest.java @@ -2,9 +2,7 @@ import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; -import com.auth0.json.mgmt.Permission; -import com.auth0.json.mgmt.PermissionSource; -import org.junit.Test; +import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; @@ -46,4 +44,4 @@ public void shouldDeserialize() throws Exception { assertThat(includedSource.getType(), is("srcType")); } -} \ No newline at end of file +} diff --git a/src/test/java/com/auth0/json/mgmt/permissions/PermissionsPageTest.java b/src/test/java/com/auth0/json/mgmt/permissions/PermissionsPageTest.java index 6261e1694..428b716ae 100644 --- a/src/test/java/com/auth0/json/mgmt/permissions/PermissionsPageTest.java +++ b/src/test/java/com/auth0/json/mgmt/permissions/PermissionsPageTest.java @@ -1,8 +1,7 @@ package com.auth0.json.mgmt.permissions; import com.auth0.json.JsonTest; -import com.auth0.json.mgmt.PermissionsPage; -import org.junit.Test; +import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; @@ -37,4 +36,4 @@ public void shouldDeserializeWithTotals() throws Exception { assertThat(page.getItems().size(), is(1)); } -} \ No newline at end of file +} diff --git a/src/test/java/com/auth0/json/mgmt/refreshtokens/RefreshTokenTest.java b/src/test/java/com/auth0/json/mgmt/refreshtokens/RefreshTokenTest.java new file mode 100644 index 000000000..a48c26505 --- /dev/null +++ b/src/test/java/com/auth0/json/mgmt/refreshtokens/RefreshTokenTest.java @@ -0,0 +1,82 @@ +package com.auth0.json.mgmt.refreshtokens; + +import com.auth0.json.JsonTest; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; + +public class RefreshTokenTest extends JsonTest { + + private static final String json = "{\n" + + " \"id\": \"tokenId1\",\n" + + " \"user_id\": \"userId1\",\n" + + " \"created_at\": \"2024-06-26T09:10:26.643Z\",\n" + + " \"idle_expires_at\": \"2024-06-26T09:10:27.131Z\",\n" + + " \"expires_at\": \"2024-07-03T09:10:26.643Z\",\n" + + " \"device\": {\n" + + " \"initial_asn\": \"1234\",\n" + + " \"initial_ip\": \"203.0.113.1\",\n" + + " \"initial_user_agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36\",\n" + + " \"last_user_agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36\",\n" + + " \"last_ip\": \"203.0.113.1\",\n" + + " \"last_asn\": \"1234\"\n" + + " },\n" + + " \"client_id\": \"clientId1\",\n" + + " \"session_id\": \"sessionId1\",\n" + + " \"rotating\": false,\n" + + " \"resource_servers\": [\n" + + " {\n" + + " \"audience\": \"https://api.example.com\",\n" + + " \"scopes\": \"offline_access\"\n" + + " }\n" + + " ],\n" + + " \"last_exchanged_at\": \"2024-07-03T09:10:26.643Z\"\n" + + "}"; + + private static final String readOnlyJson = "{\n" + + " \"user_id\": \"userId1\",\n" + + " \"client_id\": \"clientId1\",\n" + + " \"session_id\": \"sessionId1\"\n" + + "}"; + + @Test + public void shouldDeserialize() throws Exception { + RefreshToken refreshToken = fromJSON(json, RefreshToken.class); + assertThat(refreshToken, is(notNullValue())); + + assertThat(refreshToken.getId(), is("tokenId1")); + assertThat(refreshToken.getUserId(), is("userId1")); + assertThat(refreshToken.getCreatedAt(), is(parseJSONDate("2024-06-26T09:10:26.643Z"))); + assertThat(refreshToken.getIdleExpiresAt(), is(parseJSONDate("2024-06-26T09:10:27.131Z"))); + assertThat(refreshToken.getExpiresAt(), is(parseJSONDate("2024-07-03T09:10:26.643Z"))); + + assertThat(refreshToken.getDevice(), is(notNullValue())); + assertThat(refreshToken.getDevice().getInitialAsn(), is("1234")); + assertThat(refreshToken.getDevice().getInitialIp(), is("203.0.113.1")); + assertThat(refreshToken.getDevice().getInitialUserAgent(), is("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36")); + assertThat(refreshToken.getDevice().getLastUserAgent(), is("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36")); + assertThat(refreshToken.getDevice().getLastIp(), is("203.0.113.1")); + assertThat(refreshToken.getDevice().getLastAsn(), is("1234")); + + assertThat(refreshToken.getClientId(), is("clientId1")); + assertThat(refreshToken.getSessionId(), is("sessionId1")); + assertThat(refreshToken.isRotating(), is(false)); + + assertThat(refreshToken.getResourceServers(), is(notNullValue())); + assertThat(refreshToken.getResourceServers().get(0).getAudience(), is("https://api.example.com")); + assertThat(refreshToken.getResourceServers().get(0).getScopes(), is(notNullValue())); + assertThat(refreshToken.getResourceServers().get(0).getScopes(), is("offline_access")); + + assertThat(refreshToken.getLastExchangedAt(), is(parseJSONDate("2024-07-03T09:10:26.643Z"))); + } + + @Test + public void shouldIncludeReadOnlyValuesOnDeserialize() throws Exception { + RefreshToken refreshToken = fromJSON(readOnlyJson, RefreshToken.class); + assertThat(refreshToken, is(notNullValue())); + assertThat(refreshToken.getUserId(), is("userId1")); + assertThat(refreshToken.getClientId(), is("clientId1")); + assertThat(refreshToken.getSessionId(), is("sessionId1")); + } +} diff --git a/src/test/java/com/auth0/json/mgmt/refreshtokens/RefreshTokensPageTest.java b/src/test/java/com/auth0/json/mgmt/refreshtokens/RefreshTokensPageTest.java new file mode 100644 index 000000000..50a68979b --- /dev/null +++ b/src/test/java/com/auth0/json/mgmt/refreshtokens/RefreshTokensPageTest.java @@ -0,0 +1,161 @@ +package com.auth0.json.mgmt.refreshtokens; + +import com.auth0.json.JsonTest; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; + +public class RefreshTokensPageTest extends JsonTest { + private static final String json = "{\n" + + " \"tokens\": [\n" + + " {\n" + + " \"id\": \"tokenId1\",\n" + + " \"user_id\": \"userId1\",\n" + + " \"created_at\": \"2024-06-26T09:10:26.643Z\",\n" + + " \"updated_at\": \"2024-06-26T09:10:27.131Z\",\n" + + " \"expires_at\": \"2024-07-03T09:10:26.643Z\",\n" + + " \"device\": {\n" + + " \"initial_asn\": \"1234\",\n" + + " \"initial_ip\": \"203.0.113.1\",\n" + + " \"initial_user_agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36\",\n" + + " \"last_user_agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36\",\n" + + " \"last_ip\": \"203.0.113.1\",\n" + + " \"last_asn\": \"1234\"\n" + + " },\n" + + " \"client_id\": \"clientId1\",\n" + + " \"session_id\": \"sessionId1\",\n" + + " \"rotating\": false,\n" + + " \"resource_servers\": [\n" + + " {\n" + + " \"audience\": \"https://api.example.com\",\n" + + " \"scopes\": \"offline_access\"\n" + + " }\n" + + " ],\n" + + " \"last_exchanged_at\": \"2024-07-03T09:10:26.643Z\"\n" + + " },\n" + + " {\n" + + " \"id\": \"tokenId2\",\n" + + " \"user_id\": \"userId1\",\n" + + " \"created_at\": \"2024-06-26T09:10:26.643Z\",\n" + + " \"updated_at\": \"2024-06-26T09:10:27.131Z\",\n" + + " \"expires_at\": \"2024-07-03T09:10:26.643Z\",\n" + + " \"device\": {\n" + + " \"initial_asn\": \"1234\",\n" + + " \"initial_ip\": \"203.0.113.1\",\n" + + " \"initial_user_agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36\",\n" + + " \"last_user_agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36\",\n" + + " \"last_ip\": \"203.0.113.1\",\n" + + " \"last_asn\": \"1234\"\n" + + " },\n" + + " \"client_id\": \"clientId2\",\n" + + " \"session_id\": \"sessionId2\",\n" + + " \"rotating\": true,\n" + + " \"resource_servers\": [\n" + + " {\n" + + " \"audience\": \"https://api.example.com\",\n" + + " \"scopes\": \"offline_access\"\n" + + " }\n" + + " ],\n" + + " \"last_exchanged_at\": \"2024-07-03T09:10:26.643Z\"\n" + + " }\n" + + " ],\n" + + " \"next\": \"token1\"\n" + + "}"; + + private static final String jsonWithTotal = "{\n" + + " \"tokens\": [\n" + + " {\n" + + " \"id\": \"tokenId1\",\n" + + " \"user_id\": \"userId1\",\n" + + " \"created_at\": \"2024-06-26T09:10:26.643Z\",\n" + + " \"updated_at\": \"2024-06-26T09:10:27.131Z\",\n" + + " \"expires_at\": \"2024-07-03T09:10:26.643Z\",\n" + + " \"device\": {\n" + + " \"initial_asn\": \"1234\",\n" + + " \"initial_ip\": \"203.0.113.1\",\n" + + " \"initial_user_agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36\",\n" + + " \"last_user_agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36\",\n" + + " \"last_ip\": \"203.0.113.1\",\n" + + " \"last_asn\": \"1234\"\n" + + " },\n" + + " \"client_id\": \"clientId1\",\n" + + " \"session_id\": \"sessionId1\",\n" + + " \"rotating\": false,\n" + + " \"resource_servers\": [\n" + + " {\n" + + " \"audience\": \"https://api.example.com\",\n" + + " \"scopes\": \"offline_access\"\n" + + " }\n" + + " ],\n" + + " \"last_exchanged_at\": \"2024-07-03T09:10:26.643Z\"\n" + + " },\n" + + " {\n" + + " \"id\": \"tokenId2\",\n" + + " \"user_id\": \"userId1\",\n" + + " \"created_at\": \"2024-06-26T09:10:26.643Z\",\n" + + " \"updated_at\": \"2024-06-26T09:10:27.131Z\",\n" + + " \"expires_at\": \"2024-07-03T09:10:26.643Z\",\n" + + " \"device\": {\n" + + " \"initial_asn\": \"1234\",\n" + + " \"initial_ip\": \"203.0.113.1\",\n" + + " \"initial_user_agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36\",\n" + + " \"last_user_agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36\",\n" + + " \"last_ip\": \"203.0.113.1\",\n" + + " \"last_asn\": \"1234\"\n" + + " },\n" + + " \"client_id\": \"clientId2\",\n" + + " \"session_id\": \"sessionId2\",\n" + + " \"rotating\": true,\n" + + " \"resource_servers\": [\n" + + " {\n" + + " \"audience\": \"https://api.example.com\",\n" + + " \"scopes\": \"offline_access\"\n" + + " }\n" + + " ],\n" + + " \"last_exchanged_at\": \"2024-07-03T09:10:26.643Z\"\n" + + " }\n" + + " ],\n" + + " \"next\": \"token1\",\n" + + " \"total\": 11\n" + + "}"; + @Test + public void shouldDeserialize() throws Exception { + RefreshTokensPage page = fromJSON(json, RefreshTokensPage.class); + + assertThat(page.getTotal(), is(nullValue())); + assertThat(page.getNext(), is("token1")); + + assertThat(page.getTokens().size(), is(2)); + assertThat(page.getTokens().get(0).getId(), is("tokenId1")); + assertThat(page.getTokens().get(0).getUserId(), is("userId1")); + assertThat(page.getTokens().get(0).getCreatedAt(), is(parseJSONDate("2024-06-26T09:10:26.643Z"))); + assertThat(page.getTokens().get(0).getIdleExpiresAt(), is(nullValue())); + assertThat(page.getTokens().get(0).getExpiresAt(), is(parseJSONDate("2024-07-03T09:10:26.643Z"))); + + assertThat(page.getTokens().get(0).getDevice().getInitialIp(), is("203.0.113.1")); + assertThat(page.getTokens().get(0).getDevice().getInitialAsn(), is("1234")); + assertThat(page.getTokens().get(0).getDevice().getInitialUserAgent(), is("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36")); + assertThat(page.getTokens().get(0).getDevice().getLastIp(), is("203.0.113.1")); + assertThat(page.getTokens().get(0).getDevice().getLastAsn(), is("1234")); + assertThat(page.getTokens().get(0).getDevice().getLastUserAgent(), is("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36")); + + assertThat(page.getTokens().get(0).getClientId(), is("clientId1")); + assertThat(page.getTokens().get(0).getSessionId(), is("sessionId1")); + assertThat(page.getTokens().get(0).isRotating(), is(false)); + + assertThat(page.getTokens().get(0).getResourceServers().size(), is(1)); + assertThat(page.getTokens().get(0).getResourceServers().get(0).getAudience(), is("https://api.example.com")); + assertThat(page.getTokens().get(0).getResourceServers().get(0).getScopes(), is("offline_access")); + + assertThat(page.getTokens().get(0).getLastExchangedAt(), is(parseJSONDate("2024-07-03T09:10:26.643Z"))); + } + + @Test + public void shouldDeserializeWithTotal() throws Exception { + RefreshTokensPage page = fromJSON(jsonWithTotal, RefreshTokensPage.class); + + assertThat(page.getTotal(), is(11)); + } +} diff --git a/src/test/java/com/auth0/json/mgmt/selfserviceprofiles/SelfServiceProfileResponsePageTest.java b/src/test/java/com/auth0/json/mgmt/selfserviceprofiles/SelfServiceProfileResponsePageTest.java new file mode 100644 index 000000000..108e03125 --- /dev/null +++ b/src/test/java/com/auth0/json/mgmt/selfserviceprofiles/SelfServiceProfileResponsePageTest.java @@ -0,0 +1,173 @@ +package com.auth0.json.mgmt.selfserviceprofiles; + +import com.auth0.json.JsonTest; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; + +public class SelfServiceProfileResponsePageTest extends JsonTest { + + private static final String jsonWithoutTotals = + "[\n" + + " {\n" + + " \"id\": \"id1\",\n" + + " \"name\": \"test1\",\n" + + " \"description\": \"This is for testing\",\n" + + " \"user_attributes\": [\n" + + " {\n" + + " \"name\": \"Phone\",\n" + + " \"description\": \"This is Phone Number\",\n" + + " \"is_optional\": true\n" + + " }\n" + + " ],\n" + + " \"allowed_strategies\": [\n" + + " \"google-apps\"\n" + + " ],\n" + + " \"created_at\": \"2024-12-16T15:26:39.015Z\",\n" + + " \"updated_at\": \"2024-12-16T15:28:04.933Z\"\n" + + " },\n" + + " {\n" + + " \"id\": \"id2\",\n" + + " \"name\": \"Test2\",\n" + + " \"description\": \"This is for Test2\",\n" + + " \"user_attributes\": [\n" + + " {\n" + + " \"name\": \"Phone\",\n" + + " \"description\": \"This is Phone Number\",\n" + + " \"is_optional\": true\n" + + " },\n" + + " {\n" + + " \"name\": \"UserName\",\n" + + " \"description\": \"This is User Name\",\n" + + " \"is_optional\": true\n" + + " }\n" + + " ],\n" + + " \"allowed_strategies\": [\n" + + " \"oidc\"\n" + + " ],\n" + + " \"created_at\": \"2024-12-16T15:29:06.119Z\",\n" + + " \"updated_at\": \"2024-12-16T15:29:06.119Z\"\n" + + " },\n" + + " {\n" + + " \"id\": \"id3\",\n" + + " \"name\": \"Test3\",\n" + + " \"description\": \"This is a Test3\",\n" + + " \"user_attributes\": [\n" + + " {\n" + + " \"name\": \"Name\",\n" + + " \"description\": \"Name Field\",\n" + + " \"is_optional\": true\n" + + " }\n" + + " ],\n" + + " \"allowed_strategies\": [\n" + + " \"oidc\"\n" + + " ],\n" + + " \"created_at\": \"2024-12-20T09:32:13.885Z\",\n" + + " \"updated_at\": \"2024-12-20T09:32:13.885Z\",\n" + + " \"branding\": {\n" + + " \"logo_url\": \"https://www.google.com\",\n" + + " \"colors\": {\n" + + " \"primary\": \"#ffffff\"\n" + + " }\n" + + " }\n" + + " }\n" + + "]\n"; + + private static final String jsonWithTotals = + "{\n" + + " \"self_service_profiles\": [\n" + + " {\n" + + " \"id\": \"id1\",\n" + + " \"name\": \"test1\",\n" + + " \"description\": \"This is for testing\",\n" + + " \"user_attributes\": [\n" + + " {\n" + + " \"name\": \"Phone\",\n" + + " \"description\": \"This is Phone Number\",\n" + + " \"is_optional\": true\n" + + " }\n" + + " ],\n" + + " \"allowed_strategies\": [\n" + + " \"google-apps\"\n" + + " ],\n" + + " \"created_at\": \"2024-12-16T15:26:39.015Z\",\n" + + " \"updated_at\": \"2024-12-16T15:28:04.933Z\"\n" + + " },\n" + + " {\n" + + " \"id\": \"id2\",\n" + + " \"name\": \"Test2\",\n" + + " \"description\": \"This is for Test2\",\n" + + " \"user_attributes\": [\n" + + " {\n" + + " \"name\": \"Phone\",\n" + + " \"description\": \"This is Phone Number\",\n" + + " \"is_optional\": true\n" + + " },\n" + + " {\n" + + " \"name\": \"UserName\",\n" + + " \"description\": \"This is User Name\",\n" + + " \"is_optional\": true\n" + + " }\n" + + " ],\n" + + " \"allowed_strategies\": [\n" + + " \"oidc\"\n" + + " ],\n" + + " \"created_at\": \"2024-12-16T15:29:06.119Z\",\n" + + " \"updated_at\": \"2024-12-16T15:29:06.119Z\"\n" + + " },\n" + + " {\n" + + " \"id\": \"id3\",\n" + + " \"name\": \"Test3\",\n" + + " \"description\": \"This is a Test3\",\n" + + " \"user_attributes\": [\n" + + " {\n" + + " \"name\": \"Name\",\n" + + " \"description\": \"Name Field\",\n" + + " \"is_optional\": true\n" + + " }\n" + + " ],\n" + + " \"allowed_strategies\": [\n" + + " \"oidc\"\n" + + " ],\n" + + " \"created_at\": \"2024-12-20T09:32:13.885Z\",\n" + + " \"updated_at\": \"2024-12-20T09:32:13.885Z\",\n" + + " \"branding\": {\n" + + " \"logo_url\": \"https://www.google.com\",\n" + + " \"colors\": {\n" + + " \"primary\": \"#ffffff\"\n" + + " }\n" + + " }\n" + + " }\n" + + " ],\n" + + " \"start\": 0,\n" + + " \"limit\": 10,\n" + + " \"total\": 3\n" + + "}"; + + @Test + public void shouldDeserializeWithoutTotals() throws Exception { + SelfServiceProfileResponsePage page = fromJSON(jsonWithoutTotals, SelfServiceProfileResponsePage.class); + + assertThat(page, is(notNullValue())); + assertThat(page.getStart(), is(nullValue())); + assertThat(page.getTotal(), is(nullValue())); + assertThat(page.getLimit(), is(nullValue())); + assertThat(page.getItems(), is(notNullValue())); + assertThat(page.getItems().size(), is(3)); + assertThat(page.getNext(), is(nullValue())); + } + + @Test + public void shouldDeserializeWithTotals() throws Exception { + SelfServiceProfileResponsePage page = fromJSON(jsonWithTotals, SelfServiceProfileResponsePage.class); + + assertThat(page, is(notNullValue())); + assertThat(page.getStart(), is(0)); + assertThat(page.getTotal(), is(3)); + assertThat(page.getLimit(), is(10)); + assertThat(page.getItems(), is(notNullValue())); + assertThat(page.getItems().size(), is(3)); + assertThat(page.getNext(), is(nullValue())); + } +} diff --git a/src/test/java/com/auth0/json/mgmt/selfserviceprofiles/SelfServiceProfileResponseTest.java b/src/test/java/com/auth0/json/mgmt/selfserviceprofiles/SelfServiceProfileResponseTest.java new file mode 100644 index 000000000..3a1173e90 --- /dev/null +++ b/src/test/java/com/auth0/json/mgmt/selfserviceprofiles/SelfServiceProfileResponseTest.java @@ -0,0 +1,73 @@ +package com.auth0.json.mgmt.selfserviceprofiles; + +import com.auth0.json.JsonTest; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; + +import static com.auth0.json.JsonMatcher.hasEntry; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; + +public class SelfServiceProfileResponseTest extends JsonTest { + + private final static String SELF_SERVICE_PROFILE_RESPONSE_JSON = "src/test/resources/mgmt/self_service_profile_response.json"; + + @Test + public void deserialize() throws Exception { + SelfServiceProfileResponse deserialized = fromJSON(readTextFile(SELF_SERVICE_PROFILE_RESPONSE_JSON), SelfServiceProfileResponse.class); + + assertThat(deserialized.getId(), is("id")); + assertThat(deserialized.getName(), is("Test")); + assertThat(deserialized.getDescription(), is("This is a Test")); + assertThat(deserialized.getUserAttributes().get(0).getName(), is("Phone")); + assertThat(deserialized.getUserAttributes().get(0).getDescription(), is("This is Phone Number")); + assertThat(deserialized.getUserAttributes().get(0).getIsOptional(), is(true)); + assertThat(deserialized.getBranding().getColors().getPrimary(), is("#ffffff")); + assertThat(deserialized.getBranding().getLogoUrl(), is("https://www.google.com")); + assertThat(deserialized.getAllowedStrategies().get(0), is("oidc")); + assertThat(deserialized.getCreatedAt(), is("2024-12-20T09:32:13.885Z")); + assertThat(deserialized.getCreatedAt(), is("2024-12-20T09:32:13.885Z")); + } + + @Test + public void serialize() throws Exception { + SelfServiceProfileResponse selfServiceProfileResponse = new SelfServiceProfileResponse(); + selfServiceProfileResponse.setId("id"); + selfServiceProfileResponse.setName("Test"); + selfServiceProfileResponse.setDescription("This is for Test"); + + UserAttribute userAttribute = new UserAttribute("Phone", "This is Phone Number", true); + List userAttributes = new ArrayList<>(); + userAttributes.add(userAttribute); + selfServiceProfileResponse.setUserAttributes(userAttributes); + + Branding branding = new Branding(); + branding.setColors(new Color("#ffffff")); + branding.setLogoUrl("https://www.google.com"); + selfServiceProfileResponse.setBranding(branding); + + List allowedStrategies = new ArrayList<>(); + allowedStrategies.add("oidc"); + selfServiceProfileResponse.setAllowedStrategies(allowedStrategies); + + selfServiceProfileResponse.setCreatedAt("2024-12-20T09:32:13.885Z"); + selfServiceProfileResponse.setUpdatedAt("2024-12-20T09:32:13.885Z"); + + String serialized = toJSON(selfServiceProfileResponse); + assertThat(serialized, is(notNullValue())); + + assertThat(serialized, hasEntry("id", "id")); + assertThat(serialized, hasEntry("name", "Test")); + assertThat(serialized, hasEntry("description", "This is for Test")); + assertThat(serialized, hasEntry("user_attributes", notNullValue())); + assertThat(serialized, containsString("\"user_attributes\":[{\"name\":\"Phone\",\"description\":\"This is Phone Number\",\"is_optional\":true}]")); + assertThat(serialized, hasEntry("branding", notNullValue())); + assertThat(serialized, containsString("\"branding\":{\"logo_url\":\"https://www.google.com\",\"colors\":{\"primary\":\"#ffffff\"}}")); + assertThat(serialized, hasEntry("allowed_strategies", notNullValue())); + assertThat(serialized, containsString("\"allowed_strategies\":[\"oidc\"]")); + assertThat(serialized, hasEntry("created_at", "2024-12-20T09:32:13.885Z")); + assertThat(serialized, hasEntry("updated_at", "2024-12-20T09:32:13.885Z")); + } +} diff --git a/src/test/java/com/auth0/json/mgmt/selfserviceprofiles/SelfServiceProfileTest.java b/src/test/java/com/auth0/json/mgmt/selfserviceprofiles/SelfServiceProfileTest.java new file mode 100644 index 000000000..2f7e1b8c8 --- /dev/null +++ b/src/test/java/com/auth0/json/mgmt/selfserviceprofiles/SelfServiceProfileTest.java @@ -0,0 +1,62 @@ +package com.auth0.json.mgmt.selfserviceprofiles; + +import com.auth0.json.JsonTest; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; + +import static com.auth0.json.JsonMatcher.hasEntry; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; + +public class SelfServiceProfileTest extends JsonTest { + private final static String SELF_SERVICE_PROFILE_JSON = "src/test/resources/mgmt/self_service_profile.json"; + + @Test + public void deserialize() throws Exception { + SelfServiceProfile deserialized = fromJSON(readTextFile(SELF_SERVICE_PROFILE_JSON), SelfServiceProfile.class); + + assertThat(deserialized.getName(), is("Test")); + assertThat(deserialized.getDescription(), is("This is for Test")); + assertThat(deserialized.getUserAttributes().get(0).getName(), is("Phone")); + assertThat(deserialized.getUserAttributes().get(0).getDescription(), is("This is Phone Number")); + assertThat(deserialized.getUserAttributes().get(0).getIsOptional(), is(true)); + assertThat(deserialized.getBranding().getColors().getPrimary(), is("#ffffff")); + assertThat(deserialized.getBranding().getLogoUrl(), is("https://www.google.com")); + assertThat(deserialized.getAllowedStrategies().get(0), is("oidc")); + } + + @Test + public void serialize() throws Exception { + SelfServiceProfile selfServiceProfile = new SelfServiceProfile(); + selfServiceProfile.setName("Test"); + selfServiceProfile.setDescription("This is for Test"); + + UserAttribute userAttribute = new UserAttribute("Phone", "This is Phone Number", true); + List userAttributes = new ArrayList<>(); + userAttributes.add(userAttribute); + selfServiceProfile.setUserAttributes(userAttributes); + + Branding branding = new Branding(); + branding.setColors(new Color("#ffffff")); + branding.setLogoUrl("https://www.google.com"); + selfServiceProfile.setBranding(branding); + + List allowedStrategies = new ArrayList<>(); + allowedStrategies.add("oidc"); + selfServiceProfile.setAllowedStrategies(allowedStrategies); + + String serialized = toJSON(selfServiceProfile); + assertThat(serialized, is(notNullValue())); + + assertThat(serialized, hasEntry("name", "Test")); + assertThat(serialized, hasEntry("description", "This is for Test")); + assertThat(serialized, hasEntry("user_attributes", notNullValue())); + assertThat(serialized, containsString("\"user_attributes\":[{\"name\":\"Phone\",\"description\":\"This is Phone Number\",\"is_optional\":true}]")); + assertThat(serialized, hasEntry("branding", notNullValue())); + assertThat(serialized, containsString("\"branding\":{\"logo_url\":\"https://www.google.com\",\"colors\":{\"primary\":\"#ffffff\"}}")); + assertThat(serialized, hasEntry("allowed_strategies", notNullValue())); + assertThat(serialized, containsString("\"allowed_strategies\":[\"oidc\"]")); + } +} diff --git a/src/test/java/com/auth0/json/mgmt/selfserviceprofiles/SsoAccessTicketRequestTest.java b/src/test/java/com/auth0/json/mgmt/selfserviceprofiles/SsoAccessTicketRequestTest.java new file mode 100644 index 000000000..f538cb273 --- /dev/null +++ b/src/test/java/com/auth0/json/mgmt/selfserviceprofiles/SsoAccessTicketRequestTest.java @@ -0,0 +1,94 @@ +package com.auth0.json.mgmt.selfserviceprofiles; + +import com.auth0.json.JsonTest; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static com.auth0.json.JsonMatcher.hasEntry; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; + +public class SsoAccessTicketRequestTest extends JsonTest { + private final static String SELF_SERVICE_PROFILE_SSO_ACCESS_TICKET_REQUEST_JSON = "src/test/resources/mgmt/self_service_profile_sso_ticket_request.json"; + + @Test + public void deserialize() throws Exception { + SsoAccessTicketRequest deserialized = fromJSON(readTextFile(SELF_SERVICE_PROFILE_SSO_ACCESS_TICKET_REQUEST_JSON), SsoAccessTicketRequest.class); + + assertThat(deserialized.getConnectionConfig(), is(notNullValue())); + assertThat(deserialized.getEnabledClients().get(0), is("client-1")); + + assertThat(deserialized.getEnabledOrganizations().get(0).getOrganizationId(), is("org_1")); + assertThat(deserialized.getEnabledOrganizations().get(0).isAssignMembershipOnLogin(), is(true)); + assertThat(deserialized.getEnabledOrganizations().get(0).isShowAsButton(), is(true)); + + assertThat(deserialized.getTtlSec(), is(0)); + + assertThat(deserialized.getDomainAliasesConfig().getDomainVerification(), is("none")); + assertThat(deserialized.getProvisioningConfig().getScopes().get(0), is("get:users")); + } + + @Test + public void serialize() throws Exception { + Map connectionConfig = new HashMap<>(); + connectionConfig.put("name", "okta"); + connectionConfig.put("display_name", "okta connection"); + connectionConfig.put("is_domain_connection", true); + connectionConfig.put("show_as_button", true); + connectionConfig.put("metadata", new HashMap<>()); + + Map idpInitiated = new HashMap<>(); + idpInitiated.put("enabled", true); + idpInitiated.put("client_id", "client-1"); + idpInitiated.put("client_protocol", "oauth2"); + idpInitiated.put("client_authorizequery", "response_type=code&scope=openid%20profile%20email"); + + Map options = new HashMap<>(); + options.put("idpinitiated", idpInitiated); + options.put("icon_url", "https://cdn.auth0.com/connections/okta.png"); + options.put("domain_aliases", new ArrayList() {{ + add("acme.corp"); + }}); + + connectionConfig.put("options", options); + + SsoAccessTicketRequest ssoAccessTicketRequest = new SsoAccessTicketRequest(); + + ssoAccessTicketRequest.setConnectionConfig(connectionConfig); + ssoAccessTicketRequest.setEnabledClients(new ArrayList() {{ + add("client-1"); + }}); + + EnabledOrganizations enabledOrganizations = new EnabledOrganizations(); + enabledOrganizations.setOrganizationId("org_1"); + enabledOrganizations.setAssignMembershipOnLogin(true); + enabledOrganizations.setShowAsButton(true); + + ssoAccessTicketRequest.setEnabledOrganizations(new ArrayList() {{ + add(enabledOrganizations); + }}); + + ssoAccessTicketRequest.setTtlSec(0); + + ssoAccessTicketRequest.setDomainAliasesConfig(new DomainAliasesConfig("none")); + + ProvisioningConfig provisioningConfig = new ProvisioningConfig(); + List scopes = new ArrayList<>(); + scopes.add("get:users"); + provisioningConfig.setScopes(scopes); + ssoAccessTicketRequest.setProvisioningConfig(provisioningConfig); + + String serialized = toJSON(ssoAccessTicketRequest); + assertThat(ssoAccessTicketRequest, is(notNullValue())); + assertThat(serialized, containsString("{\"connection_config\":{\"metadata\":{},\"is_domain_connection\":true,\"show_as_button\":true,\"name\":\"okta\",\"options\":{\"icon_url\":\"https://cdn.auth0.com/connections/okta.png\",\"domain_aliases\":[\"acme.corp\"],\"idpinitiated\":{\"client_authorizequery\":\"response_type=code&scope=openid%20profile%20email\",\"client_protocol\":\"oauth2\",\"enabled\":true,\"client_id\":\"client-1\"}},\"display_name\":\"okta connection\"},\"enabled_clients\":[\"client-1\"],\"enabled_organizations\":[{\"organization_id\":\"org_1\",\"assign_membership_on_login\":true,\"show_as_button\":true}],\"ttl_sec\":0,\"domain_aliases_config\":{\"domain_verification\":\"none\"},\"provisioning_config\":{\"scopes\":[\"get:users\"]}}")); + assertThat(serialized, containsString("\"enabled_clients\":[\"client-1\"]")); + assertThat(serialized, containsString("\"enabled_organizations\":[{\"organization_id\":\"org_1\",\"assign_membership_on_login\":true,\"show_as_button\":true}]")); + assertThat(serialized, containsString("\"ttl_sec\":0")); + assertThat(serialized, containsString("\"domain_aliases_config\":{\"domain_verification\":\"none\"}")); + assertThat(serialized, containsString("\"provisioning_config\":{\"scopes\":[\"get:users\"]}")); + } +} diff --git a/src/test/java/com/auth0/json/mgmt/selfserviceprofiles/SsoAccessTicketResponseTest.java b/src/test/java/com/auth0/json/mgmt/selfserviceprofiles/SsoAccessTicketResponseTest.java new file mode 100644 index 000000000..3c1eb1475 --- /dev/null +++ b/src/test/java/com/auth0/json/mgmt/selfserviceprofiles/SsoAccessTicketResponseTest.java @@ -0,0 +1,31 @@ +package com.auth0.json.mgmt.selfserviceprofiles; + +import com.auth0.json.JsonTest; +import org.junit.jupiter.api.Test; + +import static com.auth0.json.JsonMatcher.hasEntry; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; + +public class SsoAccessTicketResponseTest extends JsonTest { + + private final static String SELF_SERVICE_PROFILE_SSO_TICKET_JSON = "src/test/resources/mgmt/self_service_profile_sso_ticket.json"; + + @Test + public void deserialize() throws Exception { + SsoAccessTicketResponse deserialized = fromJSON(readTextFile(SELF_SERVICE_PROFILE_SSO_TICKET_JSON), SsoAccessTicketResponse.class); + + assertThat(deserialized.getTicket(), is("https://example.auth0.com/self-service/connections-flow?ticket=ticket-1234")); + } + + @Test + public void serialize() throws Exception { + SsoAccessTicketResponse ssoAccessTicketResponse = new SsoAccessTicketResponse(); + ssoAccessTicketResponse.setTicket("https://example.auth0.com/self-service/connections-flow?ticket=ticket-1234"); + + String serialized = toJSON(ssoAccessTicketResponse); + assertThat(serialized, is(notNullValue())); + + assertThat(serialized, hasEntry("ticket", "https://example.auth0.com/self-service/connections-flow?ticket=ticket-1234")); + } +} diff --git a/src/test/java/com/auth0/json/mgmt/sessions/SessionTest.java b/src/test/java/com/auth0/json/mgmt/sessions/SessionTest.java new file mode 100644 index 000000000..8ed3d2c28 --- /dev/null +++ b/src/test/java/com/auth0/json/mgmt/sessions/SessionTest.java @@ -0,0 +1,91 @@ +package com.auth0.json.mgmt.sessions; + +import com.auth0.json.JsonTest; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; + +public class SessionTest extends JsonTest { + + private static final String json = "{\n" + + " \"id\": \"sessionId1\",\n" + + " \"user_id\": \"userId1\",\n" + + " \"created_at\": \"2024-09-04T06:41:46.145Z\",\n" + + " \"updated_at\": \"2024-09-04T06:41:46.621Z\",\n" + + " \"authenticated_at\": \"2024-09-04T06:41:46.145Z\",\n" + + " \"authentication\": {\n" + + " \"methods\": [\n" + + " {\n" + + " \"name\": \"federated\",\n" + + " \"timestamp\": \"2024-09-04T06:41:46.145Z\"\n" + + " }\n" + + " ]\n" + + " },\n" + + " \"idle_expires_at\": \"2024-09-07T06:41:46.622Z\",\n" + + " \"expires_at\": \"2024-09-11T06:41:46.145Z\",\n" + + " \"device\": {\n" + + " \"initial_user_agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36\",\n" + + " \"initial_asn\": \"1234\",\n" + + " \"initial_ip\": \"134.1.15.0\",\n" + + " \"last_user_agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36\",\n" + + " \"last_ip\": \"134.1.15.0\",\n" + + " \"last_asn\": \"1234\"\n" + + " },\n" + + " \"clients\": [\n" + + " {\n" + + " \"client_id\": \"clientId1\"\n" + + " }\n" + + " ]\n" + + "}"; + + private static final String readOnlyJson = "{\n" + + " \"user_id\": \"userId1\",\n" + + " \"clients\": [\n" + + " {\n" + + " \"client_id\": \"clientId1\"\n" + + " }\n" + + " ]\n" + + "}"; + + @Test + public void shouldDeserialize() throws Exception { + Session session = fromJSON(json, Session.class); + + assertThat(session, is(notNullValue())); + assertThat(session.getId(), is("sessionId1")); + assertThat(session.getUserId(), is("userId1")); + assertThat(session.getCreatedAt(), is(parseJSONDate("2024-09-04T06:41:46.145Z"))); + assertThat(session.getUpdatedAt(), is(parseJSONDate("2024-09-04T06:41:46.621Z"))); + assertThat(session.getAuthenticatedAt(), is(parseJSONDate("2024-09-04T06:41:46.145Z"))); + + assertThat(session.getAuthentication().getMethods(), is(notNullValue())); + assertThat(session.getAuthentication().getMethods().get(0).getName(), is("federated")); + assertThat(session.getAuthentication().getMethods().get(0).getTimestamp(), is(parseJSONDate("2024-09-04T06:41:46.145Z"))); + + assertThat(session.getIdleExpiresAt(), is(parseJSONDate("2024-09-07T06:41:46.622Z"))); + assertThat(session.getExpiresAt(), is(parseJSONDate("2024-09-11T06:41:46.145Z"))); + + assertThat(session.getDevice(), is(notNullValue())); + assertThat(session.getDevice().getInitialASN(), is("1234")); + assertThat(session.getDevice().getInitialIP(), is("134.1.15.0")); + assertThat(session.getDevice().getInitialUserAgent(), is("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36")); + assertThat(session.getDevice().getLastASN(), is("1234")); + assertThat(session.getDevice().getLastIP(), is("134.1.15.0")); + assertThat(session.getDevice().getLastUserAgent(), is("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36")); + + assertThat(session.getClients(), is(notNullValue())); + assertThat(session.getClients().get(0).getClientId(), is("clientId1")); + } + + @Test + public void shouldIncludeReadOnlyValuesOnDeserialize() throws Exception { + Session session = fromJSON(readOnlyJson, Session.class); + assertThat(session, is(notNullValue())); + assertThat(session.getUserId(), is("userId1")); + assertThat(session.getClients().get(0).getClientId(), is("clientId1")); + } + + +} diff --git a/src/test/java/com/auth0/json/mgmt/sessions/SessionsPageTest.java b/src/test/java/com/auth0/json/mgmt/sessions/SessionsPageTest.java new file mode 100644 index 000000000..12d288993 --- /dev/null +++ b/src/test/java/com/auth0/json/mgmt/sessions/SessionsPageTest.java @@ -0,0 +1,121 @@ +package com.auth0.json.mgmt.sessions; + +import com.auth0.json.JsonTest; +import com.auth0.json.mgmt.sessions.SessionsPage; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; + +public class SessionsPageTest extends JsonTest { + private static final String json = "{\n" + + " \"sessions\": [\n" + + " {\n" + + " \"id\": \"sessionId1\",\n" + + " \"user_id\": \"userId1\",\n" + + " \"created_at\": \"2024-06-26T09:10:26.643Z\",\n" + + " \"updated_at\": \"2024-06-26T09:10:27.131Z\",\n" + + " \"authenticated_at\": \"2024-06-26T09:10:26.643Z\",\n" + + " \"authentication\": {\n" + + " \"methods\": [\n" + + " {\n" + + " \"name\": \"pwd\",\n" + + " \"timestamp\": \"2024-06-26T09:10:26.643Z\"\n" + + " }\n" + + " ]\n" + + " },\n" + + " \"idle_expires_at\": \"2024-06-26T09:40:27.131Z\",\n" + + " \"expires_at\": \"2024-07-03T09:10:26.643Z\",\n" + + " \"device\": {\n" + + " \"initial_asn\": \"1234\",\n" + + " \"initial_ip\": \"203.0.113.1\",\n" + + " \"initial_user_agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36\",\n" + + " \"last_user_agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36\",\n" + + " \"last_ip\": \"203.0.113.1\",\n" + + " \"last_asn\": \"1234\"\n" + + " },\n" + + " \"clients\": [\n" + + " {\n" + + " \"client_id\": \"clientId1\"\n" + + " }\n" + + " ]\n" + + " }\n" + + " ],\n" + + " \"next\": \"sessionId1\"\n" + + "}"; + private static final String jsonWithTotals = "{\n" + + " \"sessions\": [\n" + + " {\n" + + " \"id\": \"sessionId1\",\n" + + " \"user_id\": \"userId1\",\n" + + " \"created_at\": \"2024-06-26T09:10:26.643Z\",\n" + + " \"updated_at\": \"2024-06-26T09:10:27.131Z\",\n" + + " \"authenticated_at\": \"2024-06-26T09:10:26.643Z\",\n" + + " \"authentication\": {\n" + + " \"methods\": [\n" + + " {\n" + + " \"name\": \"pwd\",\n" + + " \"timestamp\": \"2024-06-26T09:10:26.643Z\"\n" + + " }\n" + + " ]\n" + + " },\n" + + " \"idle_expires_at\": \"2024-06-26T09:40:27.131Z\",\n" + + " \"expires_at\": \"2024-07-03T09:10:26.643Z\",\n" + + " \"device\": {\n" + + " \"initial_user_agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36\",\n" + + " \"initial_asn\": \"1234\",\n" + + " \"initial_ip\": \"203.0.113.1\",\n" + + " \"last_user_agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36\",\n" + + " \"last_ip\": \"203.0.113.1\",\n" + + " \"last_asn\": \"1234\"\n" + + " },\n" + + " \"clients\": [\n" + + " {\n" + + " \"client_id\": \"clientId1\"\n" + + " }\n" + + " ]\n" + + " }\n" + + " ],\n" + + " \"next\": \"sessionId1\",\n" + + " \"total\": 11\n" + + "}"; + + @Test + public void shouldDeserialize() throws Exception { + SessionsPage page = fromJSON(json, SessionsPage.class); + + assertThat(page.getTotal(), is(nullValue())); + assertThat(page.getNext(), is("sessionId1")); + assertThat(page.getSessions().size(), is(1)); + assertThat(page.getSessions().get(0).getId(), is("sessionId1")); + assertThat(page.getSessions().get(0).getUserId(), is("userId1")); + assertThat(page.getSessions().get(0).getCreatedAt(), is(parseJSONDate("2024-06-26T09:10:26.643Z"))); + assertThat(page.getSessions().get(0).getUpdatedAt(), is(parseJSONDate("2024-06-26T09:10:27.131Z"))); + assertThat(page.getSessions().get(0).getAuthenticatedAt(), is(parseJSONDate("2024-06-26T09:10:26.643Z"))); + assertThat(page.getSessions().get(0).getIdleExpiresAt(), is(parseJSONDate("2024-06-26T09:40:27.131Z"))); + assertThat(page.getSessions().get(0).getExpiresAt(), is(parseJSONDate("2024-07-03T09:10:26.643Z"))); + + assertThat(page.getSessions().get(0).getDevice().getInitialASN(), is("1234")); + assertThat(page.getSessions().get(0).getDevice().getInitialIP(), is("203.0.113.1")); + assertThat(page.getSessions().get(0).getDevice().getLastUserAgent(), is("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36")); + assertThat(page.getSessions().get(0).getDevice().getLastIP(), is("203.0.113.1")); + assertThat(page.getSessions().get(0).getDevice().getLastASN(), is("1234")); + assertThat(page.getSessions().get(0).getDevice().getLastUserAgent(), is("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36")); + + assertThat(page.getSessions().get(0).getClients().size(), is(1)); + assertThat(page.getSessions().get(0).getClients().get(0).getClientId(), is("clientId1")); + + assertThat(page.getSessions().get(0).getAuthentication().getMethods().size(), is(1)); + assertThat(page.getSessions().get(0).getAuthentication().getMethods().get(0).getName(), is("pwd")); + assertThat(page.getSessions().get(0).getAuthentication().getMethods().get(0).getTimestamp(), is(parseJSONDate("2024-06-26T09:10:26.643Z"))); + assertThat(page.getSessions().get(0).getAuthentication().getMethods().get(0).getType(), is(nullValue())); + } + + @Test + public void shouldDeserializeWithTotals() throws Exception { + SessionsPage page = fromJSON(jsonWithTotals, SessionsPage.class); + + assertThat(page.getTotal(), is(11)); + } +} diff --git a/src/test/java/com/auth0/json/mgmt/tenants/ErrorPageCustomizationTest.java b/src/test/java/com/auth0/json/mgmt/tenants/ErrorPageCustomizationTest.java index a8476c5a3..4fa96caaf 100644 --- a/src/test/java/com/auth0/json/mgmt/tenants/ErrorPageCustomizationTest.java +++ b/src/test/java/com/auth0/json/mgmt/tenants/ErrorPageCustomizationTest.java @@ -2,7 +2,7 @@ import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; @@ -39,4 +39,4 @@ public void shouldDeserialize() throws Exception { assertThat(customization.getUrl(), is("https://page.auth0.com/main")); } -} \ No newline at end of file +} diff --git a/src/test/java/com/auth0/json/mgmt/tenants/PageCustomizationTest.java b/src/test/java/com/auth0/json/mgmt/tenants/PageCustomizationTest.java index 3a720eed4..897a85cdc 100644 --- a/src/test/java/com/auth0/json/mgmt/tenants/PageCustomizationTest.java +++ b/src/test/java/com/auth0/json/mgmt/tenants/PageCustomizationTest.java @@ -2,7 +2,7 @@ import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; @@ -33,4 +33,4 @@ public void shouldDeserialize() throws Exception { assertThat(customization.getHTML(), is("thewebpage")); } -} \ No newline at end of file +} diff --git a/src/test/java/com/auth0/json/mgmt/tenants/TenantTest.java b/src/test/java/com/auth0/json/mgmt/tenants/TenantTest.java index 3968340a2..de5f478e4 100644 --- a/src/test/java/com/auth0/json/mgmt/tenants/TenantTest.java +++ b/src/test/java/com/auth0/json/mgmt/tenants/TenantTest.java @@ -2,7 +2,8 @@ import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; -import org.junit.Test; +import com.auth0.json.mgmt.tokenquota.ClientCredentials; +import org.junit.jupiter.api.Test; import java.util.Arrays; import java.util.Collections; @@ -12,7 +13,52 @@ public class TenantTest extends JsonTest { - private static final String json = "{\"change_password\":{},\"guardian_mfa_page\":{},\"default_audience\":\"https://domain.auth0.com/myapi\",\"default_directory\":\"Username-Password-Authentication\",\"error_page\":{},\"flags\":{},\"friendly_name\":\"My-Tenant\",\"picture_url\":\"https://pic.to/123\",\"support_email\":\"support@auth0.com\",\"support_url\":\"https://support.auth0.com\",\"allowed_logout_urls\":[\"https://domain.auth0.com/logout\"], \"session_lifetime\":24, \"idle_session_lifetime\":0.5}"; + private static final String json = "{\n" + + " \"change_password\": {},\n" + + " \"guardian_mfa_page\": {},\n" + + " \"default_audience\": \"https://domain.auth0.com/myapi\",\n" + + " \"default_directory\": \"Username-Password-Authentication\",\n" + + " \"error_page\": {},\n" + + " \"flags\": {},\n" + + " \"friendly_name\": \"My-Tenant\",\n" + + " \"picture_url\": \"https://pic.to/123\",\n" + + " \"support_email\": \"support@auth0.com\",\n" + + " \"support_url\": \"https://support.auth0.com\",\n" + + " \"allowed_logout_urls\": [\n" + + " \"https://domain.auth0.com/logout\"\n" + + " ],\n" + + " \"session_lifetime\": 24,\n" + + " \"idle_session_lifetime\": 0.5,\n" + + " \"session_cookie\": {\n" + + " \"mode\": \"persistent\"\n" + + " },\n" + + " \"acr_values_supported\": [\n" + + " \"string1\",\n" + + " \"string2\"\n" + + " ],\n" + + " \"pushed_authorization_requests_supported\": true,\n" + + " \"remove_alg_from_jwks\": true,\n" + + " \"mtls\": {\n" + + " \"enable_endpoint_aliases\": true\n" + + " },\n" + + " \"default_token_quota\": {\n" + + " \"clients\": {\n" + + " \"client_credentials\": {\n" + + " \"per_day\": 100,\n" + + " \"per_hour\": 20,\n" + + " \"enforce\": true\n" + + " }\n" + + " },\n" + + " \"organizations\": {\n" + + " \"client_credentials\": {\n" + + " \"per_day\": 100,\n" + + " \"per_hour\": 20,\n" + + " \"enforce\": true\n" + + " }\n" + + " }\n" + + " }\n" + + "}"; + @Test public void shouldSerialize() throws Exception { @@ -30,6 +76,22 @@ public void shouldSerialize() throws Exception { tenant.setAllowedLogoutUrls(Collections.singletonList("https://domain.auth0.com/logout")); tenant.setSessionLifetime(48); tenant.setIdleSessionLifetime(0); + tenant.setSessionCookie(new SessionCookie("persistent")); + tenant.setAcrValuesSupported(Collections.singletonList("supported acr value")); + tenant.setPushedAuthorizationRequestsSupported(true); + tenant.setRemoveAlgFromJwks(true); + + ClientCredentials clientCredentials = new ClientCredentials(); + clientCredentials.setPerDay(100); + clientCredentials.setPerHour(20); + clientCredentials.setEnforce(true); + Clients clientTokenQuota = new Clients(clientCredentials); + Organizations organizationTokenQuota = new Organizations(clientCredentials); + tenant.setDefaultTokenQuota(new DefaultTokenQuota(clientTokenQuota, organizationTokenQuota)); + + Mtls mtls = new Mtls(); + mtls.setEnableEndpointAliases(true); + tenant.setMtls(mtls); String serialized = toJSON(tenant); assertThat(serialized, is(notNullValue())); @@ -47,6 +109,13 @@ public void shouldSerialize() throws Exception { assertThat(serialized, JsonMatcher.hasEntry("allowed_logout_urls", Arrays.asList("https://domain.auth0.com/logout"))); assertThat(serialized, JsonMatcher.hasEntry("session_lifetime", 48)); assertThat(serialized, JsonMatcher.hasEntry("idle_session_lifetime", 0)); + assertThat(serialized, JsonMatcher.hasEntry("session_cookie", notNullValue())); + assertThat(serialized, JsonMatcher.hasEntry("acr_values_supported", Collections.singletonList("supported acr value"))); + assertThat(serialized, JsonMatcher.hasEntry("pushed_authorization_requests_supported", true)); + assertThat(serialized, JsonMatcher.hasEntry("remove_alg_from_jwks", true)); + assertThat(serialized, JsonMatcher.hasEntry("enable_endpoint_aliases", notNullValue())); + assertThat(serialized, JsonMatcher.hasEntry("mtls", notNullValue())); + assertThat(serialized, JsonMatcher.hasEntry("default_token_quota", notNullValue())); } @Test @@ -67,6 +136,24 @@ public void shouldDeserialize() throws Exception { assertThat(tenant.getAllowedLogoutUrls(), contains("https://domain.auth0.com/logout")); assertThat(tenant.getSessionLifetime(), is(24)); assertThat(tenant.getIdleSessionLifetime(), is(0)); + assertThat(tenant.getSessionCookie(), is(notNullValue())); + assertThat(tenant.getSessionCookie().getMode(), is("persistent")); + assertThat(tenant.getAcrValuesSupported(), contains("string1", "string2")); + assertThat(tenant.getPushedAuthorizationRequestsSupported(), is(true)); + assertThat(tenant.getRemoveAlgFromJwks(), is(true)); + assertThat(tenant.getMtls(), is(notNullValue())); + assertThat(tenant.getMtls().getEnableEndpointAliases(), is(true)); + assertThat(tenant.getDefaultTokenQuota(), is(notNullValue())); + assertThat(tenant.getDefaultTokenQuota().getClients(), is(notNullValue())); + assertThat(tenant.getDefaultTokenQuota().getClients().getClientCredentials(), is(notNullValue())); + assertThat(tenant.getDefaultTokenQuota().getClients().getClientCredentials().getPerDay(), is(100)); + assertThat(tenant.getDefaultTokenQuota().getClients().getClientCredentials().getPerHour(), is(20)); + assertThat(tenant.getDefaultTokenQuota().getClients().getClientCredentials().isEnforce(), is(true)); + assertThat(tenant.getDefaultTokenQuota().getOrganizations(), is(notNullValue())); + assertThat(tenant.getDefaultTokenQuota().getOrganizations().getClientCredentials(), is(notNullValue())); + assertThat(tenant.getDefaultTokenQuota().getOrganizations().getClientCredentials().getPerDay(), is(100)); + assertThat(tenant.getDefaultTokenQuota().getOrganizations().getClientCredentials().getPerHour(), is(20)); + assertThat(tenant.getDefaultTokenQuota().getOrganizations().getClientCredentials().isEnforce(), is(true)); } } diff --git a/src/test/java/com/auth0/json/mgmt/tickets/EmailVerificationTicketTest.java b/src/test/java/com/auth0/json/mgmt/tickets/EmailVerificationTicketTest.java index cf31eb4aa..348066a03 100644 --- a/src/test/java/com/auth0/json/mgmt/tickets/EmailVerificationTicketTest.java +++ b/src/test/java/com/auth0/json/mgmt/tickets/EmailVerificationTicketTest.java @@ -2,8 +2,7 @@ import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; -import com.auth0.json.mgmt.EmailVerificationIdentity; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.HashMap; import java.util.Map; diff --git a/src/test/java/com/auth0/json/mgmt/tickets/PasswordChangeTicketTest.java b/src/test/java/com/auth0/json/mgmt/tickets/PasswordChangeTicketTest.java index 74996f5e9..ce73ce755 100644 --- a/src/test/java/com/auth0/json/mgmt/tickets/PasswordChangeTicketTest.java +++ b/src/test/java/com/auth0/json/mgmt/tickets/PasswordChangeTicketTest.java @@ -2,7 +2,7 @@ import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; diff --git a/src/test/java/com/auth0/json/mgmt/userAttributeProfiles/ListUserAttributeProfileTemplateTest.java b/src/test/java/com/auth0/json/mgmt/userAttributeProfiles/ListUserAttributeProfileTemplateTest.java new file mode 100644 index 000000000..2c7c69be9 --- /dev/null +++ b/src/test/java/com/auth0/json/mgmt/userAttributeProfiles/ListUserAttributeProfileTemplateTest.java @@ -0,0 +1,144 @@ +package com.auth0.json.mgmt.userAttributeProfiles; + +import com.auth0.json.JsonMatcher; +import com.auth0.json.JsonTest; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static com.auth0.json.JsonMatcher.hasEntry; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.hasKey; + +public class ListUserAttributeProfileTemplateTest extends JsonTest { + + private static final String jsonWithTemplates = "{\n" + + " \"user_attribute_profile_templates\": [\n" + + " {\n" + + " \"id\": \"auth0-generic\",\n" + + " \"display_name\": \"Auth0 Generic User Attribute Profile Template\",\n" + + " \"template\": {\n" + + " \"name\": \"This is just a test\",\n" + + " \"user_id\": {\n" + + " \"oidc_mapping\": \"sub\",\n" + + " \"saml_mapping\": [\n" + + " \"urn:oid:0.9.10.10.100.1.1\"\n" + + " ],\n" + + " \"scim_mapping\": \"userName\"\n" + + " },\n" + + " \"user_attributes\": {\n" + + " \"username\": {\n" + + " \"label\": \"test User\",\n" + + " \"description\": \"This is just a test\",\n" + + " \"oidc_mapping\": {\n" + + " \"mapping\": \"preferred_username\",\n" + + " \"display_name\": \"UserName\"\n" + + " },\n" + + " \"saml_mapping\": [\n" + + " \"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress\"\n" + + " ],\n" + + " \"scim_mapping\": \"displayName\",\n" + + " \"auth0_mapping\": \"testUser\",\n" + + " \"profile_required\": false,\n" + + " \"strategy_overrides\": {\n" + + " \"oidc\": {\n" + + " \"scim_mapping\": \"name.givenName\"\n" + + " }\n" + + " }\n" + + " }\n" + + " }\n" + + " }\n" + + " }\n" + + " ]\n" + + "}"; + + private static final String emptyListJson = "{\n" + + " \"user_attribute_profile_templates\": []\n" + + "}"; + + @Test + public void shouldSerialize() throws Exception { + ListUserAttributeProfileTemplate listTemplates = new ListUserAttributeProfileTemplate(); + + UserAttributeProfileTemplate template = new UserAttributeProfileTemplate(); + template.setDisplayName("Auth0 Generic User Attribute Profile Template"); + + // Create nested UserAttributeProfile for template1 + UserAttributeProfile userProfile = new UserAttributeProfile(); + userProfile.setName("This is just a test"); + template.setTemplate(userProfile); + + listTemplates.setUserAttributeProfileTemplates(Arrays.asList(template)); + + String serialized = toJSON(listTemplates); + assertThat(serialized, is(notNullValue())); + assertThat(serialized, hasEntry("display_name", "Auth0 Generic User Attribute Profile Template")); + assertThat(serialized, hasEntry("template", notNullValue())); + } + + @Test + public void shouldDeserialize() throws Exception { + ListUserAttributeProfileTemplate listTemplates = fromJSON(jsonWithTemplates, + ListUserAttributeProfileTemplate.class); + + assertThat(listTemplates, is(notNullValue())); + assertThat(listTemplates.getUserAttributeProfileTemplates(), is(notNullValue())); + assertThat(listTemplates.getUserAttributeProfileTemplates(), hasSize(1)); + + List templates = listTemplates.getUserAttributeProfileTemplates(); + assertThat(templates, hasSize(1)); + + // Test template details + UserAttributeProfileTemplate template = templates.get(0); + assertThat(template.getId(), is("auth0-generic")); + assertThat(template.getDisplayName(), is("Auth0 Generic User Attribute Profile Template")); + + // Test nested UserAttributeProfile template + UserAttributeProfile userAttributeProfile = template.getTemplate(); + assertThat(userAttributeProfile, is(notNullValue())); + assertThat(userAttributeProfile.getName(), is("This is just a test")); + + // Test UserId in nested template + UserId userId = userAttributeProfile.getUserId(); + assertThat(userId, is(notNullValue())); + assertThat(userId.getOidcMapping(), is("sub")); + assertThat(userId.getSamlMapping(), hasSize(1)); + assertThat(userId.getSamlMapping().get(0), is("urn:oid:0.9.10.10.100.1.1")); + assertThat(userId.getScimMapping(), is("userName")); + + // Test UserAttributes in nested template + Map userAttributes = userAttributeProfile.getUserAttributes(); + assertThat(userAttributes, is(notNullValue())); + assertThat(userAttributes, hasKey("username")); + + UserAttributes usernameAttr = userAttributes.get("username"); + assertThat(usernameAttr, is(notNullValue())); + assertThat(usernameAttr.getLabel(), is("test User")); + assertThat(usernameAttr.getDescription(), is("This is just a test")); + assertThat(usernameAttr.getAuth0Mapping(), is("testUser")); + assertThat(usernameAttr.isProfileRequired(), is(false)); + + // Test OIDC mapping in nested template + assertThat(usernameAttr.getOidcMapping(), is(notNullValue())); + assertThat(usernameAttr.getOidcMapping().getMapping(), is("preferred_username")); + assertThat(usernameAttr.getOidcMapping().getDisplayName(), is("UserName")); + + // Test SAML mapping in nested template + assertThat(usernameAttr.getSamlMapping(), hasSize(1)); + assertThat(usernameAttr.getSamlMapping().get(0), + is("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress")); + + // Test SCIM mapping in nested template + assertThat(usernameAttr.getScimMapping(), is("displayName")); + + // Test strategy overrides in nested template + assertThat(usernameAttr.getStrategyOverrides(), is(notNullValue())); + assertThat(usernameAttr.getStrategyOverrides(), hasKey("oidc")); + } +} diff --git a/src/test/java/com/auth0/json/mgmt/userAttributeProfiles/UserAttributeProfileTemplateTest.java b/src/test/java/com/auth0/json/mgmt/userAttributeProfiles/UserAttributeProfileTemplateTest.java new file mode 100644 index 000000000..67c0dbccc --- /dev/null +++ b/src/test/java/com/auth0/json/mgmt/userAttributeProfiles/UserAttributeProfileTemplateTest.java @@ -0,0 +1,132 @@ +package com.auth0.json.mgmt.userAttributeProfiles; + +import com.auth0.json.JsonTest; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.hasKey; +import static org.hamcrest.Matchers.hasSize; + +public class UserAttributeProfileTemplateTest extends JsonTest { + + + private static final String fullJson = "{\n" + + " \"id\": \"auth0-generic\",\n" + + " \"display_name\": \"A standard user attribute profile template\",\n" + + " \"template\": {\n" + + " \"name\": \"This is just a test\",\n" + + " \"user_id\": {\n" + + " \"oidc_mapping\": \"sub\",\n" + + " \"saml_mapping\": [\n" + + " \"urn:oid:0.9.10.10.100.1.1\"\n" + + " ],\n" + + " \"scim_mapping\": \"userName\"\n" + + " },\n" + + " \"user_attributes\": {\n" + + " \"username\": {\n" + + " \"label\": \"test User\",\n" + + " \"description\": \"This is just a test\",\n" + + " \"oidc_mapping\": {\n" + + " \"mapping\": \"preferred_username\",\n" + + " \"display_name\": \"UserName\"\n" + + " },\n" + + " \"saml_mapping\":[\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress\"],\n" + + " \"scim_mapping\":\"displayName\",\n" + + " \"auth0_mapping\": \"testUser\",\n" + + " \"profile_required\": false,\n" + + " \"strategy_overrides\": {\n" + + " \"oidc\": {\n" + + " \"scim_mapping\":\"name.givenName\"\n" + + " }\n" + + " }\n" + + " }\n" + + " }\n" + + " }\n" + + "}"; + + @Test + public void shouldSerialize() throws Exception { + UserAttributeProfileTemplate template = new UserAttributeProfileTemplate(); + template.setDisplayName("A standard user attribute profile template"); + + // Create nested UserAttributeProfile template + UserAttributeProfile userAttributeProfile = new UserAttributeProfile(); + userAttributeProfile.setName("Test Template Profile"); + + // Create and set UserId + UserId userId = new UserId(); + userId.setOidcMapping("sub"); + userId.setSamlMapping(Arrays.asList("urn:oid:0.9.10.10.100.1.1")); + userId.setScimMapping("userName"); + userAttributeProfile.setUserId(userId); + + // Create and set UserAttributes + Map userAttributesMap = new HashMap<>(); + UserAttributes userAttributes = new UserAttributes(); + userAttributes.setLabel("test User"); + userAttributes.setDescription("This is just a test"); + userAttributes.setAuth0Mapping("testUser"); + userAttributes.setProfileRequired(false); + userAttributesMap.put("username", userAttributes); + userAttributeProfile.setUserAttributes(userAttributesMap); + + template.setTemplate(userAttributeProfile); + + String serialized = toJSON(template); + assertThat(serialized, is(notNullValue())); + + // Parse the serialized JSON into a Map + ObjectMapper objectMapper = new ObjectMapper(); + Map jsonMap = objectMapper.readValue(serialized, Map.class); + + // Validate the structure + assertThat(jsonMap, hasKey("display_name")); + assertThat(jsonMap.get("display_name"), is("A standard user attribute profile template")); + assertThat(jsonMap, hasKey("template")); + + Map templateMap = (Map) jsonMap.get("template"); + assertThat(templateMap, hasKey("name")); + assertThat(templateMap.get("name"), is("Test Template Profile")); + } + + @Test + public void shouldDeserialize() throws Exception { + UserAttributeProfileTemplate template = fromJSON(fullJson, UserAttributeProfileTemplate.class); + + assertThat(template, is(notNullValue())); + assertThat(template.getId(), is("auth0-generic")); + assertThat(template.getDisplayName(), is("A standard user attribute profile template")); + + // Verify nested UserAttributeProfile template + UserAttributeProfile userAttributeProfile = template.getTemplate(); + assertThat(userAttributeProfile, is(notNullValue())); + assertThat(userAttributeProfile.getName(), is("This is just a test")); + + // Verify UserId in template + UserId userId = userAttributeProfile.getUserId(); + assertThat(userId, is(notNullValue())); + assertThat(userId.getOidcMapping(), is("sub")); + assertThat(userId.getSamlMapping(), hasSize(1)); + assertThat(userId.getSamlMapping().get(0), is("urn:oid:0.9.10.10.100.1.1")); + assertThat(userId.getScimMapping(), is("userName")); + + // Verify UserAttributes in template + Map userAttributes = userAttributeProfile.getUserAttributes(); + assertThat(userAttributes, is(notNullValue())); + assertThat(userAttributes, hasKey("username")); + + UserAttributes usernameAttr = userAttributes.get("username"); + assertThat(usernameAttr, is(notNullValue())); + assertThat(usernameAttr.getLabel(), is("test User")); + assertThat(usernameAttr.getDescription(), is("This is just a test")); + assertThat(usernameAttr.getAuth0Mapping(), is("testUser")); + assertThat(usernameAttr.isProfileRequired(), is(false)); + } +} diff --git a/src/test/java/com/auth0/json/mgmt/userAttributeProfiles/UserAttributeProfileTest.java b/src/test/java/com/auth0/json/mgmt/userAttributeProfiles/UserAttributeProfileTest.java new file mode 100644 index 000000000..28cbf9e4e --- /dev/null +++ b/src/test/java/com/auth0/json/mgmt/userAttributeProfiles/UserAttributeProfileTest.java @@ -0,0 +1,132 @@ +package com.auth0.json.mgmt.userAttributeProfiles; + +import com.auth0.json.JsonTest; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.hasKey; +import static org.hamcrest.Matchers.hasSize; + +public class UserAttributeProfileTest extends JsonTest { + + private static final String fullJson = "{\n" + + " \"id\": \"uap_1234567890\",\n" + + " \"name\": \"This is just a test\",\n" + + " \"user_id\": {\n" + + " \"oidc_mapping\": \"sub\",\n" + + " \"saml_mapping\": [\n" + + " \"urn:oid:0.9.10.10.100.1.1\"\n" + + " ],\n" + + " \"scim_mapping\": \"userName\"\n" + + " },\n" + + " \"user_attributes\": {\n" + + " \"username\": {\n" + + " \"label\": \"test User\",\n" + + " \"description\": \"This is just a test\",\n" + + " \"oidc_mapping\": {\n" + + " \"mapping\": \"preferred_username\",\n" + + " \"display_name\": \"UserName\"\n" + + " },\n" + + " \"saml_mapping\":[\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress\"],\n" + + " \"scim_mapping\":\"displayName\",\n" + + " \"auth0_mapping\": \"testUser\",\n" + + " \"profile_required\": false,\n" + + " \"strategy_overrides\": {\n" + + " \"oidc\": {\n" + + " \"scim_mapping\":\"name.givenName\"\n" + + " }\n" + + " }\n" + + " }\n" + + " }\n" + + "}"; + + @Test + public void shouldSerialize() throws Exception { + UserAttributeProfile profile = new UserAttributeProfile(); + profile.setName("Test Profile"); + + // Create and set UserId + UserId userId = new UserId(); + userId.setOidcMapping("sub"); + userId.setSamlMapping(Arrays.asList("urn:oid:0.9.10.10.100.1.1")); + userId.setScimMapping("userName"); + profile.setUserId(userId); + + // Create and set UserAttributes + Map userAttributesMap = new HashMap<>(); + UserAttributes userAttributes = new UserAttributes(); + userAttributes.setLabel("test User"); + userAttributes.setDescription("This is just a test"); + userAttributes.setAuth0Mapping("testUser"); + userAttributes.setProfileRequired(false); + userAttributesMap.put("username", userAttributes); + profile.setUserAttributes(userAttributesMap); + + String serialized = toJSON(profile); + assertThat(serialized, is(notNullValue())); + + // Parse the serialized JSON into a Map + ObjectMapper objectMapper = new ObjectMapper(); + Map jsonMap = objectMapper.readValue(serialized, Map.class); + + // Validate the structure + assertThat(jsonMap, hasKey("name")); + assertThat(jsonMap.get("name"), is("Test Profile")); + assertThat(jsonMap, hasKey("user_id")); + assertThat(jsonMap, hasKey("user_attributes")); + } + + @Test + public void shouldDeserialize() throws Exception { + UserAttributeProfile profile = fromJSON(fullJson, UserAttributeProfile.class); + + assertThat(profile, is(notNullValue())); + assertThat(profile.getId(), is("uap_1234567890")); + assertThat(profile.getName(), is("This is just a test")); + + // Verify UserId deserialization + UserId userId = profile.getUserId(); + assertThat(userId, is(notNullValue())); + assertThat(userId.getOidcMapping(), is("sub")); + assertThat(userId.getSamlMapping(), hasSize(1)); + assertThat(userId.getSamlMapping().get(0), is("urn:oid:0.9.10.10.100.1.1")); + assertThat(userId.getScimMapping(), is("userName")); + + // Verify UserAttributes deserialization + Map userAttributes = profile.getUserAttributes(); + assertThat(userAttributes, is(notNullValue())); + assertThat(userAttributes, hasKey("username")); + + UserAttributes usernameAttr = userAttributes.get("username"); + assertThat(usernameAttr, is(notNullValue())); + assertThat(usernameAttr.getLabel(), is("test User")); + assertThat(usernameAttr.getDescription(), is("This is just a test")); + assertThat(usernameAttr.getAuth0Mapping(), is("testUser")); + assertThat(usernameAttr.isProfileRequired(), is(false)); + + // Verify OIDC mapping + assertThat(usernameAttr.getOidcMapping(), is(notNullValue())); + assertThat(usernameAttr.getOidcMapping().getMapping(), is("preferred_username")); + assertThat(usernameAttr.getOidcMapping().getDisplayName(), is("UserName")); + + // Verify SAML mapping + assertThat(usernameAttr.getSamlMapping(), hasSize(1)); + assertThat(usernameAttr.getSamlMapping().get(0), + is("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress")); + + // Verify SCIM mapping + assertThat(usernameAttr.getScimMapping(), is("displayName")); + + // Verify strategy overrides + assertThat(usernameAttr.getStrategyOverrides(), is(notNullValue())); + assertThat(usernameAttr.getStrategyOverrides(), hasKey("oidc")); + } + +} diff --git a/src/test/java/com/auth0/json/mgmt/userblocks/BlockDetailsTest.java b/src/test/java/com/auth0/json/mgmt/userblocks/BlockDetailsTest.java index 68c93e221..d8efdba30 100644 --- a/src/test/java/com/auth0/json/mgmt/userblocks/BlockDetailsTest.java +++ b/src/test/java/com/auth0/json/mgmt/userblocks/BlockDetailsTest.java @@ -1,7 +1,7 @@ package com.auth0.json.mgmt.userblocks; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; @@ -19,4 +19,4 @@ public void shouldDeserialize() throws Exception { assertThat(details.getIdentifier(), is("username")); assertThat(details.getIP(), is("10.0.0.1")); } -} \ No newline at end of file +} diff --git a/src/test/java/com/auth0/json/mgmt/userblocks/UserBlocksTest.java b/src/test/java/com/auth0/json/mgmt/userblocks/UserBlocksTest.java index 046579128..e51d244a7 100644 --- a/src/test/java/com/auth0/json/mgmt/userblocks/UserBlocksTest.java +++ b/src/test/java/com/auth0/json/mgmt/userblocks/UserBlocksTest.java @@ -1,7 +1,7 @@ package com.auth0.json.mgmt.userblocks; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; @@ -18,4 +18,4 @@ public void shouldDeserialize() throws Exception { assertThat(blocks.getBlockedFor(), is(notNullValue())); assertThat(blocks.getBlockedFor(), hasSize(2)); } -} \ No newline at end of file +} diff --git a/src/test/java/com/auth0/json/mgmt/users/IdentityTest.java b/src/test/java/com/auth0/json/mgmt/users/IdentityTest.java index 679eeb8b2..914f98102 100644 --- a/src/test/java/com/auth0/json/mgmt/users/IdentityTest.java +++ b/src/test/java/com/auth0/json/mgmt/users/IdentityTest.java @@ -1,7 +1,7 @@ package com.auth0.json.mgmt.users; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; diff --git a/src/test/java/com/auth0/json/mgmt/users/ProfileDataTest.java b/src/test/java/com/auth0/json/mgmt/users/ProfileDataTest.java index 2b1e7ef55..fae21fabf 100644 --- a/src/test/java/com/auth0/json/mgmt/users/ProfileDataTest.java +++ b/src/test/java/com/auth0/json/mgmt/users/ProfileDataTest.java @@ -1,7 +1,7 @@ package com.auth0.json.mgmt.users; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; diff --git a/src/test/java/com/auth0/json/mgmt/users/RecoveryCodeTest.java b/src/test/java/com/auth0/json/mgmt/users/RecoveryCodeTest.java index 97ec6eb79..9533baf59 100644 --- a/src/test/java/com/auth0/json/mgmt/users/RecoveryCodeTest.java +++ b/src/test/java/com/auth0/json/mgmt/users/RecoveryCodeTest.java @@ -1,7 +1,7 @@ package com.auth0.json.mgmt.users; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; @@ -18,4 +18,4 @@ public void shouldDeserialize() throws Exception { assertThat(code, is(notNullValue())); assertThat(code.getCode(), is("supersecretCODE")); } -} \ No newline at end of file +} diff --git a/src/test/java/com/auth0/json/mgmt/users/UserTest.java b/src/test/java/com/auth0/json/mgmt/users/UserTest.java index 558cbc856..0d0cc3dae 100644 --- a/src/test/java/com/auth0/json/mgmt/users/UserTest.java +++ b/src/test/java/com/auth0/json/mgmt/users/UserTest.java @@ -2,14 +2,12 @@ import com.auth0.json.JsonMatcher; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.Collections; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.notNullValue; -import static org.hamcrest.Matchers.nullValue; +import static org.hamcrest.Matchers.*; import static org.hamcrest.collection.IsMapContaining.hasEntry; public class UserTest extends JsonTest { diff --git a/src/test/java/com/auth0/json/mgmt/users/UsersPageTest.java b/src/test/java/com/auth0/json/mgmt/users/UsersPageTest.java index 76497b278..6e0095dd4 100644 --- a/src/test/java/com/auth0/json/mgmt/users/UsersPageTest.java +++ b/src/test/java/com/auth0/json/mgmt/users/UsersPageTest.java @@ -1,7 +1,7 @@ package com.auth0.json.mgmt.users; import com.auth0.json.JsonTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.ArrayList; diff --git a/src/test/java/com/auth0/json/mgmt/users/authenticationmethods/AuthenticationMethodTest.java b/src/test/java/com/auth0/json/mgmt/users/authenticationmethods/AuthenticationMethodTest.java new file mode 100644 index 000000000..bbe8c9a8a --- /dev/null +++ b/src/test/java/com/auth0/json/mgmt/users/authenticationmethods/AuthenticationMethodTest.java @@ -0,0 +1,94 @@ +package com.auth0.json.mgmt.users.authenticationmethods; + +import com.auth0.json.JsonMatcher; +import com.auth0.json.JsonTest; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.core.Is.is; + +public class AuthenticationMethodTest extends JsonTest { + + @Test + public void shouldDeserialize() throws Exception { + String orgJson = "{\n" + + " \"id\":\"email|dev_1cIsjj3hICWeOWTb\",\n" + + " \"type\":\"email\",\n" + + " \"confirmed\":true,\n" + + " \"email\":\"****@temp****\",\n" + + " \"name\":\"name\",\n" + + " \"link_id\":\"linkId\",\n" + + " \"phone_number\":\"1231212312\",\n" + + " \"key_id\":\"keyId\",\n" + + " \"public_key\":\"publicKey\",\n" + + " \"created_at\":\"2023-01-19T15:15:16.427Z\",\n" + + " \"enrolled_at\":\"2023-01-19T15:15:16.427Z\",\n" + + " \"last_auth_at\":\"2023-01-19T15:15:16.427Z\",\n" + + " \"last_auth_at\":\"2023-01-19T15:15:16.427Z\",\n" + + " \"totp_secret\":\"totp\",\n" + + " \"preferred_authentication_method\":\"phone\",\n" + + " \"relying_party_identifier\":\"abc\",\n" + + " \"authentication_methods\":[{\"id\": \"id\", \"type\": \"type\"}],\n" + + " \"credential_device_type\": \"single_device\",\n" + + " \"credential_backed_up\": true,\n" + + " \"identity_user_id\": \"identityId\",\n" + + " \"user_agent\": \"userAgent\"" + + " }"; + + + AuthenticationMethod authenticationMethod = fromJSON(orgJson, AuthenticationMethod.class); + assertThat(authenticationMethod, is(notNullValue())); + assertThat(authenticationMethod.getId(), is("email|dev_1cIsjj3hICWeOWTb")); + assertThat(authenticationMethod.getType(), is("email")); + assertThat(authenticationMethod.getName(), is("name")); + assertThat(authenticationMethod.getLinkId(), is("linkId")); + assertThat(authenticationMethod.getPhoneNumber(), is("1231212312")); + assertThat(authenticationMethod.getKeyId(), is("keyId")); + assertThat(authenticationMethod.getPublicKey(), is("publicKey")); + assertThat(authenticationMethod.getTotpSecret(), is("totp")); + assertThat(authenticationMethod.getPreferredAuthenticationMethod(), is("phone")); + assertThat(authenticationMethod.getRelyingPartyIdentifier(), is("abc")); + assertThat(authenticationMethod.getConfirmed(), is(true)); + assertThat(authenticationMethod.getEmail(), is("****@temp****")); + assertThat(authenticationMethod.getCreatedAt(), is(parseJSONDate(("2023-01-19T15:15:16.427Z")))); + assertThat(authenticationMethod.getLastAuthedAt(), is(parseJSONDate(("2023-01-19T15:15:16.427Z")))); + assertThat(authenticationMethod.getEnrolledAt(), is(parseJSONDate(("2023-01-19T15:15:16.427Z")))); + assertThat(authenticationMethod.getAuthenticationMethods(), hasSize(1)); + assertThat(authenticationMethod.getAuthenticationMethods().get(0).getId(), is("id")); + assertThat(authenticationMethod.getAuthenticationMethods().get(0).getType(), is("type")); + assertThat(authenticationMethod.getCredentialDeviceType(), is("single_device")); + assertThat(authenticationMethod.getCredentialBackedUp(), is(true)); + assertThat(authenticationMethod.getIdentityUserId(), is("identityId")); + assertThat(authenticationMethod.getUserAgent(), is("userAgent")); + } + + @Test + public void shouldSerialize() throws Exception { + AuthenticationMethod authenticationMethod = new AuthenticationMethod(); + + authenticationMethod.setType("phone"); + authenticationMethod.setName("abc"); + authenticationMethod.setPhoneNumber("1231212312"); + authenticationMethod.setKeyId("keyid"); + authenticationMethod.setPublicKey("pubkey"); + authenticationMethod.setTotpSecret("totp"); + authenticationMethod.setPreferredAuthenticationMethod("phone"); + authenticationMethod.setRelyingPartyIdentifier("123"); + authenticationMethod.setEmail("temp@temp.com"); + + String serialized = toJSON(authenticationMethod); + assertThat(serialized, is(notNullValue())); + assertThat(serialized, JsonMatcher.hasEntry("type", "phone")); + assertThat(serialized, JsonMatcher.hasEntry("name", "abc")); + assertThat(serialized, JsonMatcher.hasEntry("phone_number", "1231212312")); + assertThat(serialized, JsonMatcher.hasEntry("key_id", "keyid")); + assertThat(serialized, JsonMatcher.hasEntry("public_key", "pubkey")); + assertThat(serialized, JsonMatcher.hasEntry("totp_secret", "totp")); + assertThat(serialized, JsonMatcher.hasEntry("preferred_authentication_method", "phone")); + assertThat(serialized, JsonMatcher.hasEntry("relying_party_identifier", "123")); + assertThat(serialized, JsonMatcher.hasEntry("email", "temp@temp.com")); + } +} + diff --git a/src/test/java/com/auth0/net/BaseRequestTest.java b/src/test/java/com/auth0/net/BaseRequestTest.java index 75fc67c2f..4521e8bd9 100644 --- a/src/test/java/com/auth0/net/BaseRequestTest.java +++ b/src/test/java/com/auth0/net/BaseRequestTest.java @@ -1,20 +1,39 @@ package com.auth0.net; +import com.auth0.AssertsUtil; +import com.auth0.client.MockServer; +import com.auth0.client.mgmt.TokenProvider; import com.auth0.exception.APIException; import com.auth0.exception.Auth0Exception; import com.auth0.exception.RateLimitException; -import okhttp3.Request; -import okhttp3.*; -import org.junit.Before; -import org.junit.Test; +import com.auth0.json.auth.TokenHolder; +import com.auth0.net.client.*; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import okhttp3.mockwebserver.RecordedRequest; +import org.hamcrest.Matchers; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import java.io.IOException; +import java.util.List; +import java.util.Map; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import static com.auth0.AssertsUtil.verifyThrows; +import static com.auth0.client.MockServer.*; +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; // FIXME: These test require mocking of the final class okhttp3.Response. To do so // an opt-in incubating Mockito feature is used, for more information see: @@ -22,231 +41,467 @@ // This issue can be tracked to see if/when this feature will become standard for Mockito (perhaps Mockito 4): // https://github.com/mockito/mockito/issues/1728 public class BaseRequestTest { + private MockServer server; + private Auth0HttpClient client; + private TokenProvider tokenProvider; - private Response response; - private Call call; - private OkHttpClient client; + private TypeReference tokenHolderType; + private TypeReference listType; + private TypeReference voidType; - @Before + @BeforeEach public void setUp() throws Exception { - response = mock(Response.class); + server = new MockServer(); + client = DefaultHttpClient.newBuilder().withMaxRetries(0).build(); + tokenHolderType = new TypeReference() { + }; + listType = new TypeReference() { + }; + voidType = new TypeReference() { + }; + tokenProvider = new TokenProvider() { + @Override + public String getToken() { + return "xyz"; + } + @Override + public CompletableFuture getTokenAsync() { + return CompletableFuture.completedFuture("xyz"); + } + }; + } + + @AfterEach + public void tearDown() throws Exception { + server.stop(); + } + + @Test + public void handlesIOException() throws Exception { + DefaultHttpClient client = mock(DefaultHttpClient.class); + when(client.sendRequest(any())).thenThrow(IOException.class); + + BaseRequest req = new BaseRequest(client, tokenProvider, "", HttpMethod.GET, new TypeReference() { + }) { + @Override + public BaseRequest addHeader(String name, String value) { + return null; + } + + @Override + public BaseRequest addParameter(String name, Object value) { + return null; + } + + @Override + public BaseRequest setBody(Object body) { + return null; + } + + @Override + protected Auth0HttpRequest createRequest(String apiToken) { + return null; + } + + @Override + protected String parseResponseBody(Auth0HttpResponse response) { + return null; + } + }; + + Auth0Exception exception = verifyThrows(Auth0Exception.class, req::execute); + assertThat(exception.getCause(), is(instanceOf(IOException.class))); + } + + @Test + public void asyncHandlesIOExceptionWhenCreatingRequest() { + DefaultHttpClient client = DefaultHttpClient.newBuilder().build(); + + BaseRequest req = new BaseRequest(client, tokenProvider, "", HttpMethod.GET, new TypeReference() { + }) { + @Override + public BaseRequest addHeader(String name, String value) { + return null; + } + + @Override + public BaseRequest addParameter(String name, Object value) { + return null; + } + + @Override + public BaseRequest setBody(Object body) { + return null; + } + + @Override + protected Auth0HttpRequest createRequest(String apiToken) throws Auth0Exception { + throw new Auth0Exception("error", new IOException("boom")); + } + + @Override + protected String parseResponseBody(Auth0HttpResponse response) { + return null; + } + }; + + Auth0HttpRequest a0Request = Auth0HttpRequest.newBuilder("https://foo.com", HttpMethod.GET).build(); + CompletableFuture> future = req.executeAsync(); + ExecutionException e = verifyThrows(ExecutionException.class, future::get); + assertThat(e.getCause(), is(instanceOf(IOException.class))); + } + + @Test + public void shouldCreateGETRequest() throws Exception { + BaseRequest request = new BaseRequest<>(client, tokenProvider, server.getBaseUrl(), HttpMethod.GET, tokenHolderType); + assertThat(request, Matchers.is(notNullValue())); + + server.jsonResponse(AUTH_TOKENS, 200); + TokenHolder execute = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + assertThat(recordedRequest.getMethod(), Matchers.is(HttpMethod.GET.toString())); + assertThat(execute, Matchers.is(notNullValue())); + } + + @Test + public void shouldCreatePOSTRequest() throws Exception { + BaseRequest request = new BaseRequest<>(client, tokenProvider, server.getBaseUrl(), HttpMethod.POST, tokenHolderType); + assertThat(request, Matchers.is(notNullValue())); + request.addParameter("non_empty", "body"); + + server.jsonResponse(AUTH_TOKENS, 200); + TokenHolder execute = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + assertThat(recordedRequest.getMethod(), Matchers.is(HttpMethod.POST.toString())); + assertThat(execute, Matchers.is(notNullValue())); + } + + @Test + public void shouldAddParameters() throws Exception { + BaseRequest request = new BaseRequest<>(client, tokenProvider, server.getBaseUrl(), HttpMethod.POST, tokenHolderType); + Map mapValue = mock(Map.class); + request.addParameter("key", "value"); + request.addParameter("map", mapValue); + + server.jsonResponse(AUTH_TOKENS, 200); + request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + Map values = bodyFromRequest(recordedRequest); + assertThat(values, hasEntry("key", "value")); + assertThat(values, hasEntry("map", mapValue)); + } + + @Test + public void shouldAddHeaders() throws Exception { + BaseRequest request = new BaseRequest<>(client, tokenProvider, server.getBaseUrl(), HttpMethod.POST, tokenHolderType); + request.addParameter("non_empty", "body"); + request.addHeader("Extra-Info", "this is a test"); + request.addHeader("Authorization", "Bearer my_access_token"); + request.addHeader("X-Client-Quota", getTokenQuotaString()); + request.addHeader("X-Organization-Quota", getTokenQuotaString()); + + server.jsonResponse(AUTH_TOKENS, 200); + request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest.getHeader("Extra-Info"), Matchers.is("this is a test")); + // auth header will be done on the request handling + assertThat(recordedRequest.getHeader("Authorization"), Matchers.is("Bearer xyz")); + } + + @Test + public void shouldNotOverrideContentTypeHeader() throws Exception { + BaseRequest request = new BaseRequest<>(client, tokenProvider, server.getBaseUrl(), HttpMethod.POST, tokenHolderType); + request.addParameter("non_empty", "body"); + request.addHeader("Content-Type", "plaintext"); + + server.jsonResponse(AUTH_TOKENS, 200); + request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest.getHeader("Content-Type"), Matchers.is("application/json")); + } - call = mock(Call.class); - when(call.execute()).thenReturn(response); + @Test + public void shouldThrowOnBodyCreationFailure() throws Exception { + ObjectMapper mapper = mock(ObjectMapper.class); + when(mapper.writeValueAsBytes(any(Object.class))).thenThrow(JsonProcessingException.class); + + BaseRequest request = new BaseRequest<>(client, tokenProvider, server.getBaseUrl(), HttpMethod.POST, mapper, voidType); + request.addParameter("name", "value"); - client = mock(OkHttpClient.class); - when(client.newCall(any())).thenReturn(call); + Auth0Exception e = AssertsUtil.verifyThrows(Auth0Exception.class, + () -> request.execute().getBody(), + "Couldn't create the request body."); + assertThat(e.getCause(), Matchers.instanceOf(JsonProcessingException.class)); } @Test - public void alwaysCloseResponseOnSuccessfulRequest() { + public void shouldParseSuccessfulResponse() throws Exception { + BaseRequest request = new BaseRequest<>(client, tokenProvider, server.getBaseUrl(), HttpMethod.GET, tokenHolderType); + server.jsonResponse(AUTH_TOKENS, 200); + TokenHolder response = request.execute().getBody(); + server.takeRequest(); + + assertThat(response, Matchers.is(notNullValue())); + assertThat(response.getAccessToken(), not(emptyOrNullString())); + assertThat(response.getIdToken(), not(emptyOrNullString())); + assertThat(response.getRefreshToken(), not(emptyOrNullString())); + assertThat(response.getTokenType(), not(emptyOrNullString())); + assertThat(response.getExpiresIn(), Matchers.is(notNullValue())); + } + + @Test + public void shouldThrowOnParseInvalidSuccessfulResponse() throws Exception { + BaseRequest request = new BaseRequest<>(client, tokenProvider, server.getBaseUrl(), HttpMethod.GET, listType); + server.jsonResponse(AUTH_TOKENS, 200); Exception exception = null; try { - new MockBaseRequest(client) { - @Override - protected String parseResponse(Response response) { - return ""; - } - }.execute(); + request.execute().getBody(); + server.takeRequest(); } catch (Exception e) { exception = e; } - - assertThat(exception, is(nullValue())); - verify(response, times(1)).close(); + assertThat(exception, Matchers.is(notNullValue())); + assertThat(exception, Matchers.is(Matchers.instanceOf(APIException.class))); + assertThat(exception.getCause(), Matchers.is(Matchers.instanceOf(JsonMappingException.class))); + assertThat(exception.getMessage(), Matchers.is("Request failed with status code 200: Failed to parse the response body.")); + APIException authException = (APIException) exception; + assertThat(authException.getDescription(), Matchers.is("Failed to parse the response body.")); + assertThat(authException.getError(), Matchers.is(nullValue())); + assertThat(authException.getStatusCode(), Matchers.is(200)); } @Test - public void alwaysCloseResponseOnRateLimitException() { + public void shouldParseJSONErrorResponseWithErrorDescription() throws Exception { + BaseRequest request = new BaseRequest<>(client, tokenProvider, server.getBaseUrl(), HttpMethod.GET, listType); + server.jsonResponse(AUTH_ERROR_WITH_ERROR_DESCRIPTION, 400); Exception exception = null; try { - new MockBaseRequest(client) { - @Override - protected String parseResponse(Response response) throws Auth0Exception { - throw new RateLimitException(-1, -1, -1); - } - }.execute(); + request.execute().getBody(); + server.takeRequest(); } catch (Exception e) { exception = e; } - - assertThat(exception, is(notNullValue())); - assertThat(exception, is(instanceOf(RateLimitException.class))); - assertThat(exception.getMessage(), is("Request failed with status code 429: Rate limit reached")); - verify(response, times(1)).close(); + assertThat(exception, Matchers.is(notNullValue())); + assertThat(exception, Matchers.is(Matchers.instanceOf(APIException.class))); + assertThat(exception.getCause(), Matchers.is(nullValue())); + assertThat(exception.getMessage(), Matchers.is("Request failed with status code 400: the connection was not found")); + APIException authException = (APIException) exception; + assertThat(authException.getDescription(), Matchers.is("the connection was not found")); + assertThat(authException.getError(), Matchers.is("invalid_request")); + assertThat(authException.getStatusCode(), Matchers.is(400)); } @Test - public void alwaysCloseResponseOnAPIException() { + public void shouldParseJSONErrorResponseWithError() throws Exception { + BaseRequest request = new BaseRequest<>(client, tokenProvider, server.getBaseUrl(), HttpMethod.GET, listType); + server.jsonResponse(AUTH_ERROR_WITH_ERROR, 400); Exception exception = null; try { - new MockBaseRequest(client) { - @Override - protected String parseResponse(Response response) throws Auth0Exception { - throw new APIException("APIException", 500, null); - } - }.execute(); + request.execute().getBody(); + server.takeRequest(); } catch (Exception e) { exception = e; } - - assertThat(exception, is(notNullValue())); - assertThat(exception, is(instanceOf(APIException.class))); - assertThat(exception.getMessage(), is("Request failed with status code 500: APIException")); - verify(response, times(1)).close(); + assertThat(exception, Matchers.is(notNullValue())); + assertThat(exception, Matchers.is(Matchers.instanceOf(APIException.class))); + assertThat(exception.getCause(), Matchers.is(nullValue())); + assertThat(exception.getMessage(), Matchers.is("Request failed with status code 400: missing username for Username-Password-Authentication connection with requires_username enabled")); + APIException authException = (APIException) exception; + assertThat(authException.getDescription(), Matchers.is("missing username for Username-Password-Authentication connection with requires_username enabled")); + assertThat(authException.getError(), Matchers.is("missing username for Username-Password-Authentication connection with requires_username enabled")); + assertThat(authException.getStatusCode(), Matchers.is(400)); } + @SuppressWarnings("RedundantCast") @Test - public void alwaysCloseResponseOnAuth0Exception() { + public void shouldParseJSONErrorResponseWithDescriptionAndExtraProperties() throws Exception { + BaseRequest request = new BaseRequest<>(client, tokenProvider, server.getBaseUrl(), HttpMethod.GET, listType); + server.jsonResponse(AUTH_ERROR_WITH_DESCRIPTION_AND_EXTRA_PROPERTIES, 400); Exception exception = null; try { - new MockBaseRequest(client) { - @Override - protected String parseResponse(Response response) throws Auth0Exception { - throw new Auth0Exception("Auth0Exception"); - } - }.execute(); + request.execute().getBody(); + server.takeRequest(); } catch (Exception e) { exception = e; } - - assertThat(exception, is(notNullValue())); - assertThat(exception, is(instanceOf(Auth0Exception.class))); - assertThat(exception.getMessage(), is("Auth0Exception")); - verify(response, times(1)).close(); + assertThat(exception, Matchers.is(notNullValue())); + assertThat(exception, Matchers.is(Matchers.instanceOf(APIException.class))); + assertThat(exception.getCause(), Matchers.is(nullValue())); + assertThat(exception.getMessage(), Matchers.is("Request failed with status code 400: Multifactor authentication required")); + APIException authException = (APIException) exception; + assertThat(authException.getDescription(), Matchers.is("Multifactor authentication required")); + assertThat(authException.getError(), Matchers.is("mfa_required")); + assertThat(authException.getValue("mfa_token"), Matchers.is((Object) "Fe26...Ha")); + assertThat(authException.getValue("non_existing_key"), Matchers.is(nullValue())); + assertThat(authException.getStatusCode(), Matchers.is(400)); } @Test - public void asyncCompletesWithExceptionWhenRequestCreationFails() throws Exception { - CompletableFuture request = new MockBaseRequest(client) { - @Override - protected Request parseResponse(Response response) throws Auth0Exception { - throw new Auth0Exception("Response Parsing Error"); - } - @Override - protected Request createRequest() throws Auth0Exception { - throw new Auth0Exception("Create Request Error"); - } - }.executeAsync(); - + public void shouldParseJSONErrorResponseWithDescription() throws Exception { + BaseRequest request = new BaseRequest<>(client, tokenProvider, server.getBaseUrl(), HttpMethod.GET, listType); + server.jsonResponse(AUTH_ERROR_WITH_DESCRIPTION, 400); Exception exception = null; - Object result = null; - try { - result = request.get(); + request.execute().getBody(); + server.takeRequest(); } catch (Exception e) { exception = e; } - - assertThat(result, is(nullValue())); - assertThat(exception, is(notNullValue())); - assertThat(exception.getCause(), is(instanceOf(Auth0Exception.class))); - assertThat(exception.getCause().getMessage(), is("Create Request Error")); + assertThat(exception, Matchers.is(notNullValue())); + assertThat(exception, Matchers.is(Matchers.instanceOf(APIException.class))); + assertThat(exception.getCause(), Matchers.is(nullValue())); + assertThat(exception.getMessage(), Matchers.is("Request failed with status code 400: The user already exists.")); + APIException authException = (APIException) exception; + assertThat(authException.getDescription(), Matchers.is("The user already exists.")); + assertThat(authException.getError(), Matchers.is("user_exists")); + assertThat(authException.getStatusCode(), Matchers.is(400)); } @Test - public void asyncCompletesWithExceptionWhenRequestFails() throws Exception { - doReturn(call).when(client).newCall(any()); - - doAnswer(invocation -> { - ((Callback) invocation.getArgument(0)).onFailure(call, new IOException("Error!")); - return null; - }).when(call).enqueue(any()); - - CompletableFuture request = new MockBaseRequest(client) { - @Override - protected String parseResponse(Response response) throws Auth0Exception { - throw new Auth0Exception("Response Parsing Error"); - } - }.executeAsync(); - + public void shouldParseJSONErrorResponseWithMessage() throws Exception { + BaseRequest request = new BaseRequest<>(client, tokenProvider, server.getBaseUrl(), HttpMethod.GET, listType); + server.jsonResponse(MGMT_ERROR_WITH_MESSAGE, 400); Exception exception = null; - Object result = null; - try { - result = request.get(); + request.execute().getBody(); + server.takeRequest(); } catch (Exception e) { exception = e; } - - assertThat(exception, is(notNullValue())); - assertThat(result, is(nullValue())); - assertThat(exception.getCause(), is(instanceOf(Auth0Exception.class))); - assertThat(exception.getCause().getMessage(), is("Failed to execute request")); - assertThat(exception.getCause().getCause(), is(instanceOf(IOException.class))); - assertThat(exception.getCause().getCause().getMessage(), is("Error!")); + assertThat(exception, Matchers.is(notNullValue())); + assertThat(exception, Matchers.is(Matchers.instanceOf(APIException.class))); + assertThat(exception.getCause(), Matchers.is(nullValue())); + assertThat(exception.getMessage(), Matchers.is("Request failed with status code 400: Query validation error: 'String 'invalid_field' does not match pattern. Must be a comma separated list of the following values: allowed_logout_urls,change_password.")); + APIException authException = (APIException) exception; + assertThat(authException.getDescription(), Matchers.is("Query validation error: 'String 'invalid_field' does not match pattern. Must be a comma separated list of the following values: allowed_logout_urls,change_password.")); + assertThat(authException.getError(), Matchers.is("invalid_query_string")); + assertThat(authException.getStatusCode(), Matchers.is(400)); } @Test - public void asyncCompletesWithExceptionWhenResponseParsingFails() throws Exception { - doReturn(call).when(client).newCall(any()); - - doAnswer(invocation -> { - ((Callback) invocation.getArgument(0)).onResponse(call, response); - return null; - }).when(call).enqueue(any()); - - CompletableFuture request = new MockBaseRequest(client) { - @Override - protected String parseResponse(Response response) throws Auth0Exception { - throw new Auth0Exception("Response Parsing Error"); - } - }.executeAsync(); - + public void shouldParsePlainTextErrorResponse() throws Exception { + BaseRequest request = new BaseRequest<>(client, tokenProvider, server.getBaseUrl(), HttpMethod.GET, listType); + server.textResponse(AUTH_ERROR_PLAINTEXT, 400); Exception exception = null; - Object result = null; - try { - result = request.get(); + request.execute().getBody(); + server.takeRequest(); } catch (Exception e) { exception = e; } - - assertThat(result, is(nullValue())); - assertThat(exception, is(notNullValue())); - assertThat(exception.getCause(), is(instanceOf(Auth0Exception.class))); - assertThat(exception.getCause().getMessage(), is("Response Parsing Error")); + assertThat(exception, Matchers.is(notNullValue())); + assertThat(exception, Matchers.is(Matchers.instanceOf(APIException.class))); + assertThat(exception.getCause(), Matchers.is(Matchers.instanceOf(JsonParseException.class))); + assertThat(exception.getMessage(), Matchers.is("Request failed with status code 400: A plain-text error response")); + APIException authException = (APIException) exception; + assertThat(authException.getDescription(), Matchers.is("A plain-text error response")); + assertThat(authException.getError(), Matchers.is(nullValue())); + assertThat(authException.getValue("non_existing_key"), Matchers.is(nullValue())); + assertThat(authException.getStatusCode(), Matchers.is(400)); } @Test - public void asyncCompletesSuccessfully() { - doReturn(call).when(client).newCall(any()); - - doAnswer(invocation -> { - ((Callback) invocation.getArgument(0)).onResponse(call, response); - return null; - }).when(call).enqueue(any()); - - CompletableFuture request = new MockBaseRequest(client) { - @Override - protected String parseResponse(Response response) throws Auth0Exception { - return "Success"; - } - }.executeAsync(); + public void shouldParseRateLimitException() throws Exception { + BaseRequest request = new BaseRequest<>(client, tokenProvider, server.getBaseUrl(), HttpMethod.GET, listType); + server.rateLimitReachedResponse(100, 10, 5, RATE_LIMIT_ERROR); + Exception exception = null; + try { + request.execute().getBody(); + server.takeRequest(); + } catch (Exception e) { + exception = e; + } + assertThat(exception, Matchers.is(notNullValue())); + assertThat(exception, Matchers.is(Matchers.instanceOf(RateLimitException.class))); + assertThat(exception.getCause(), Matchers.is(nullValue())); + assertThat(exception.getMessage(), Matchers.is("Request failed with status code 429: Global limit has been reached")); + RateLimitException rateLimitException = (RateLimitException) exception; + assertThat(rateLimitException.getDescription(), Matchers.is("Global limit has been reached")); + assertThat(rateLimitException.getError(), Matchers.is("too_many_requests")); + assertThat(rateLimitException.getValue("non_existing_key"), Matchers.is(nullValue())); + assertThat(rateLimitException.getStatusCode(), Matchers.is(429)); + assertThat(rateLimitException.getLimit(), Matchers.is(100L)); + assertThat(rateLimitException.getRemaining(), Matchers.is(10L)); + assertThat(rateLimitException.getReset(), Matchers.is(5L)); + } + @Test + public void shouldParseRateLimitExceptionWithZeroRemaining() throws Exception { + BaseRequest request = new BaseRequest<>(client, tokenProvider, server.getBaseUrl(), HttpMethod.GET, listType); + server.rateLimitReachedResponse(100, 0, 5, RATE_LIMIT_ERROR, getTokenQuotaString(), getTokenQuotaString(), 1000); Exception exception = null; - Object result = null; + try { + request.execute().getBody(); + server.takeRequest(); + } catch (Exception e) { + exception = e; + } + assertThat(exception, Matchers.is(notNullValue())); + assertThat(exception, Matchers.is(Matchers.instanceOf(RateLimitException.class))); + assertThat(exception.getCause(), Matchers.is(nullValue())); + assertThat(exception.getMessage(), Matchers.is("Request failed with status code 429: Global limit has been reached")); + RateLimitException rateLimitException = (RateLimitException) exception; + assertThat(rateLimitException.getDescription(), Matchers.is("Global limit has been reached")); + assertThat(rateLimitException.getError(), Matchers.is("too_many_requests")); + assertThat(rateLimitException.getValue("non_existing_key"), Matchers.is(nullValue())); + assertThat(rateLimitException.getStatusCode(), Matchers.is(429)); + assertThat(rateLimitException.getLimit(), Matchers.is(100L)); + assertThat(rateLimitException.getRemaining(), Matchers.is(0L)); + assertThat(rateLimitException.getReset(), Matchers.is(5L)); + assertThat(rateLimitException.getClientQuotaLimit().getPerDay().getQuota(), Matchers.is(getTokenQuota().getPerDay().getQuota())); + assertThat(rateLimitException.getOrganizationQuotaLimit().getPerDay().getQuota(), Matchers.is(getTokenQuota().getPerDay().getQuota())); + } + @Test + public void shouldDefaultRateLimitsHeadersWhenMissing() throws Exception { + BaseRequest request = new BaseRequest<>(client, tokenProvider, server.getBaseUrl(), HttpMethod.GET, listType); + server.rateLimitReachedResponse(-1, -1, -1); + Exception exception = null; try { - result = request.get(); + request.execute().getBody(); + server.takeRequest(); } catch (Exception e) { exception = e; } + assertThat(exception, Matchers.is(notNullValue())); + assertThat(exception, Matchers.is(Matchers.instanceOf(RateLimitException.class))); + assertThat(exception.getCause(), Matchers.is(nullValue())); + assertThat(exception.getMessage(), Matchers.is("Request failed with status code 429: Rate limit reached")); + RateLimitException rateLimitException = (RateLimitException) exception; + assertThat(rateLimitException.getDescription(), Matchers.is("Rate limit reached")); + assertThat(rateLimitException.getError(), Matchers.is(nullValue())); + assertThat(rateLimitException.getValue("non_existing_key"), Matchers.is(nullValue())); + assertThat(rateLimitException.getStatusCode(), Matchers.is(429)); + assertThat(rateLimitException.getLimit(), Matchers.is(-1L)); + assertThat(rateLimitException.getRemaining(), Matchers.is(-1L)); + assertThat(rateLimitException.getReset(), Matchers.is(-1L)); + assertThat(rateLimitException.getClientQuotaLimit(), Matchers.is(nullValue())); + assertThat(rateLimitException.getOrganizationQuotaLimit(), Matchers.is(nullValue())); + } - assertThat(exception, is(nullValue())); - assertThat(result, is(instanceOf(String.class))); - assertThat(result, is("Success")); + private TokenQuotaBucket getTokenQuota() { + TokenQuotaLimit perHourLimit = new TokenQuotaLimit(100, 80, 3600); + TokenQuotaLimit perDayLimit = new TokenQuotaLimit(100, 90, 86400); + return new TokenQuotaBucket(perHourLimit, perDayLimit); } - private abstract static class MockBaseRequest extends BaseRequest { - MockBaseRequest(OkHttpClient client) { - super(client); - } + public String getTokenQuotaString() { + TokenQuotaLimit perHourLimit = new TokenQuotaLimit(100, 80, 3600); + TokenQuotaLimit perDayLimit = new TokenQuotaLimit(100, 90, 86400); + + StringBuilder builder = new StringBuilder(); - @Override - protected Request createRequest() throws Auth0Exception { - return null; + builder.append(String.format("b=per_hour;q=%d;r=%d;t=%d", + perHourLimit.getQuota(), perHourLimit.getRemaining(), perHourLimit.getResetAfter())); + + if (builder.length() > 0) { + builder.append(","); } - } + builder.append(String.format("b=per_day;q=%d;r=%d;t=%d", + perDayLimit.getQuota(), perDayLimit.getRemaining(), perDayLimit.getResetAfter())); + return builder.toString(); + } } diff --git a/src/test/java/com/auth0/net/CustomRequestTest.java b/src/test/java/com/auth0/net/CustomRequestTest.java deleted file mode 100644 index 124860a2d..000000000 --- a/src/test/java/com/auth0/net/CustomRequestTest.java +++ /dev/null @@ -1,370 +0,0 @@ -package com.auth0.net; - -import com.auth0.client.MockServer; -import com.auth0.exception.APIException; -import com.auth0.exception.Auth0Exception; -import com.auth0.exception.RateLimitException; -import com.auth0.json.auth.TokenHolder; -import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.JsonMappingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import okhttp3.Call; -import okhttp3.OkHttpClient; -import okhttp3.mockwebserver.RecordedRequest; -import org.hamcrest.Matchers; -import org.junit.*; -import org.junit.rules.ExpectedException; - -import java.io.IOException; -import java.util.List; -import java.util.Map; - -import static com.auth0.client.MockServer.*; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class CustomRequestTest { - private MockServer server; - private OkHttpClient client; - - @SuppressWarnings("deprecation") - @Rule - public ExpectedException exception = ExpectedException.none(); - private TypeReference tokenHolderType; - private TypeReference listType; - private TypeReference voidType; - - @Before - public void setUp() throws Exception { - server = new MockServer(); - client = new OkHttpClient(); - tokenHolderType = new TypeReference() { - }; - listType = new TypeReference() { - }; - voidType = new TypeReference() { - }; - } - - @After - public void tearDown() throws Exception { - server.stop(); - } - - @Test - public void shouldCreateGETRequest() throws Exception { - CustomRequest request = new CustomRequest<>(client, server.getBaseUrl(), "GET", tokenHolderType); - assertThat(request, is(notNullValue())); - - server.jsonResponse(AUTH_TOKENS, 200); - TokenHolder execute = request.execute(); - RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest.getMethod(), is("GET")); - assertThat(execute, is(notNullValue())); - } - - @Test - public void shouldCreatePOSTRequest() throws Exception { - CustomRequest request = new CustomRequest<>(client, server.getBaseUrl(), "POST", tokenHolderType); - assertThat(request, is(notNullValue())); - request.addParameter("non_empty", "body"); - - server.jsonResponse(AUTH_TOKENS, 200); - TokenHolder execute = request.execute(); - RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest.getMethod(), is("POST")); - assertThat(execute, is(notNullValue())); - } - - @Test - public void shouldAddParameters() throws Exception { - CustomRequest request = new CustomRequest<>(client, server.getBaseUrl(), "POST", tokenHolderType); - Map mapValue = mock(Map.class); - request.addParameter("key", "value"); - request.addParameter("map", mapValue); - - server.jsonResponse(AUTH_TOKENS, 200); - request.execute(); - RecordedRequest recordedRequest = server.takeRequest(); - Map values = bodyFromRequest(recordedRequest); - assertThat(values, hasEntry("key", "value")); - assertThat(values, hasEntry("map", mapValue)); - } - - @Test - public void shouldAddHeaders() throws Exception { - CustomRequest request = new CustomRequest<>(client, server.getBaseUrl(), "POST", tokenHolderType); - request.addParameter("non_empty", "body"); - request.addHeader("Extra-Info", "this is a test"); - request.addHeader("Authorization", "Bearer my_access_token"); - - server.jsonResponse(AUTH_TOKENS, 200); - request.execute(); - RecordedRequest recordedRequest = server.takeRequest(); - - assertThat(recordedRequest.getHeader("Extra-Info"), is("this is a test")); - assertThat(recordedRequest.getHeader("Authorization"), is("Bearer my_access_token")); - } - - @Test - public void shouldNotOverrideContentTypeHeader() throws Exception { - CustomRequest request = new CustomRequest<>(client, server.getBaseUrl(), "POST", tokenHolderType); - request.addParameter("non_empty", "body"); - request.addHeader("Content-Type", "plaintext"); - - server.jsonResponse(AUTH_TOKENS, 200); - request.execute(); - RecordedRequest recordedRequest = server.takeRequest(); - - assertThat(recordedRequest.getHeader("Content-Type"), is("application/json")); - } - - @Test - public void shouldThrowOnExecuteFailure() throws Exception { - exception.expect(Auth0Exception.class); - exception.expectCause(Matchers.instanceOf(IOException.class)); - exception.expectMessage("Failed to execute request"); - - OkHttpClient client = mock(OkHttpClient.class); - Call call = mock(Call.class); - when(client.newCall(any(okhttp3.Request.class))).thenReturn(call); - when(call.execute()).thenThrow(IOException.class); - CustomRequest request = new CustomRequest<>(client, server.getBaseUrl(), "GET", voidType); - request.execute(); - } - - @Test - public void shouldThrowOnBodyCreationFailure() throws Exception { - ObjectMapper mapper = mock(ObjectMapper.class); - when(mapper.writeValueAsBytes(any(Object.class))).thenThrow(JsonProcessingException.class); - - CustomRequest request = new CustomRequest<>(client, server.getBaseUrl(), "POST", mapper, voidType); - request.addParameter("name", "value"); - exception.expect(Auth0Exception.class); - exception.expectCause(Matchers.instanceOf(JsonProcessingException.class)); - exception.expectMessage("Couldn't create the request body."); - request.execute(); - } - - @Test - public void shouldParseSuccessfulResponse() throws Exception { - CustomRequest request = new CustomRequest<>(client, server.getBaseUrl(), "GET", tokenHolderType); - server.jsonResponse(AUTH_TOKENS, 200); - TokenHolder response = request.execute(); - server.takeRequest(); - - assertThat(response, is(notNullValue())); - assertThat(response.getAccessToken(), not(emptyOrNullString())); - assertThat(response.getIdToken(), not(emptyOrNullString())); - assertThat(response.getRefreshToken(), not(emptyOrNullString())); - assertThat(response.getTokenType(), not(emptyOrNullString())); - assertThat(response.getExpiresIn(), is(notNullValue())); - } - - @Test - public void shouldThrowOnParseInvalidSuccessfulResponse() throws Exception { - CustomRequest request = new CustomRequest<>(client, server.getBaseUrl(), "GET", listType); - server.jsonResponse(AUTH_TOKENS, 200); - Exception exception = null; - try { - request.execute(); - server.takeRequest(); - } catch (Exception e) { - exception = e; - } - assertThat(exception, is(notNullValue())); - assertThat(exception, is(instanceOf(APIException.class))); - assertThat(exception.getCause(), is(instanceOf(JsonMappingException.class))); - assertThat(exception.getMessage(), is("Request failed with status code 200: Failed to parse the response body.")); - APIException authException = (APIException) exception; - assertThat(authException.getDescription(), is("Failed to parse the response body.")); - assertThat(authException.getError(), is(nullValue())); - assertThat(authException.getStatusCode(), is(200)); - } - - @Test - public void shouldParseJSONErrorResponseWithErrorDescription() throws Exception { - CustomRequest request = new CustomRequest<>(client, server.getBaseUrl(), "GET", listType); - server.jsonResponse(AUTH_ERROR_WITH_ERROR_DESCRIPTION, 400); - Exception exception = null; - try { - request.execute(); - server.takeRequest(); - } catch (Exception e) { - exception = e; - } - assertThat(exception, is(notNullValue())); - assertThat(exception, is(instanceOf(APIException.class))); - assertThat(exception.getCause(), is(nullValue())); - assertThat(exception.getMessage(), is("Request failed with status code 400: the connection was not found")); - APIException authException = (APIException) exception; - assertThat(authException.getDescription(), is("the connection was not found")); - assertThat(authException.getError(), is("invalid_request")); - assertThat(authException.getStatusCode(), is(400)); - } - - @Test - public void shouldParseJSONErrorResponseWithError() throws Exception { - CustomRequest request = new CustomRequest<>(client, server.getBaseUrl(), "GET", listType); - server.jsonResponse(AUTH_ERROR_WITH_ERROR, 400); - Exception exception = null; - try { - request.execute(); - server.takeRequest(); - } catch (Exception e) { - exception = e; - } - assertThat(exception, is(notNullValue())); - assertThat(exception, is(instanceOf(APIException.class))); - assertThat(exception.getCause(), is(nullValue())); - assertThat(exception.getMessage(), is("Request failed with status code 400: missing username for Username-Password-Authentication connection with requires_username enabled")); - APIException authException = (APIException) exception; - assertThat(authException.getDescription(), is("missing username for Username-Password-Authentication connection with requires_username enabled")); - assertThat(authException.getError(), is("missing username for Username-Password-Authentication connection with requires_username enabled")); - assertThat(authException.getStatusCode(), is(400)); - } - - @SuppressWarnings("RedundantCast") - @Test - public void shouldParseJSONErrorResponseWithDescriptionAndExtraProperties() throws Exception { - CustomRequest request = new CustomRequest<>(client, server.getBaseUrl(), "GET", listType); - server.jsonResponse(AUTH_ERROR_WITH_DESCRIPTION_AND_EXTRA_PROPERTIES, 400); - Exception exception = null; - try { - request.execute(); - server.takeRequest(); - } catch (Exception e) { - exception = e; - } - assertThat(exception, is(notNullValue())); - assertThat(exception, is(instanceOf(APIException.class))); - assertThat(exception.getCause(), is(nullValue())); - assertThat(exception.getMessage(), is("Request failed with status code 400: Multifactor authentication required")); - APIException authException = (APIException) exception; - assertThat(authException.getDescription(), is("Multifactor authentication required")); - assertThat(authException.getError(), is("mfa_required")); - assertThat(authException.getValue("mfa_token"), is((Object) "Fe26...Ha")); - assertThat(authException.getValue("non_existing_key"), is(nullValue())); - assertThat(authException.getStatusCode(), is(400)); - } - - @Test - public void shouldParseJSONErrorResponseWithDescription() throws Exception { - CustomRequest request = new CustomRequest<>(client, server.getBaseUrl(), "GET", listType); - server.jsonResponse(AUTH_ERROR_WITH_DESCRIPTION, 400); - Exception exception = null; - try { - request.execute(); - server.takeRequest(); - } catch (Exception e) { - exception = e; - } - assertThat(exception, is(notNullValue())); - assertThat(exception, is(instanceOf(APIException.class))); - assertThat(exception.getCause(), is(nullValue())); - assertThat(exception.getMessage(), is("Request failed with status code 400: The user already exists.")); - APIException authException = (APIException) exception; - assertThat(authException.getDescription(), is("The user already exists.")); - assertThat(authException.getError(), is("user_exists")); - assertThat(authException.getStatusCode(), is(400)); - } - - @Test - public void shouldParseJSONErrorResponseWithMessage() throws Exception { - CustomRequest request = new CustomRequest<>(client, server.getBaseUrl(), "GET", listType); - server.jsonResponse(MGMT_ERROR_WITH_MESSAGE, 400); - Exception exception = null; - try { - request.execute(); - server.takeRequest(); - } catch (Exception e) { - exception = e; - } - assertThat(exception, is(notNullValue())); - assertThat(exception, is(instanceOf(APIException.class))); - assertThat(exception.getCause(), is(nullValue())); - assertThat(exception.getMessage(), is("Request failed with status code 400: Query validation error: 'String 'invalid_field' does not match pattern. Must be a comma separated list of the following values: allowed_logout_urls,change_password.")); - APIException authException = (APIException) exception; - assertThat(authException.getDescription(), is("Query validation error: 'String 'invalid_field' does not match pattern. Must be a comma separated list of the following values: allowed_logout_urls,change_password.")); - assertThat(authException.getError(), is("invalid_query_string")); - assertThat(authException.getStatusCode(), is(400)); - } - - @Test - public void shouldParsePlainTextErrorResponse() throws Exception { - CustomRequest request = new CustomRequest<>(client, server.getBaseUrl(), "GET", listType); - server.textResponse(AUTH_ERROR_PLAINTEXT, 400); - Exception exception = null; - try { - request.execute(); - server.takeRequest(); - } catch (Exception e) { - exception = e; - } - assertThat(exception, is(notNullValue())); - assertThat(exception, is(instanceOf(APIException.class))); - assertThat(exception.getCause(), is(instanceOf(JsonParseException.class))); - assertThat(exception.getMessage(), is("Request failed with status code 400: A plain-text error response")); - APIException authException = (APIException) exception; - assertThat(authException.getDescription(), is("A plain-text error response")); - assertThat(authException.getError(), is(nullValue())); - assertThat(authException.getValue("non_existing_key"), is(nullValue())); - assertThat(authException.getStatusCode(), is(400)); - } - - @Test - public void shouldParseRateLimitsHeaders() { - CustomRequest request = new CustomRequest<>(client, server.getBaseUrl(), "GET", listType); - server.rateLimitReachedResponse(100, 10, 5); - Exception exception = null; - try { - request.execute(); - server.takeRequest(); - } catch (Exception e) { - exception = e; - } - assertThat(exception, is(notNullValue())); - assertThat(exception, is(instanceOf(RateLimitException.class))); - assertThat(exception.getCause(), is(nullValue())); - assertThat(exception.getMessage(), is("Request failed with status code 429: Rate limit reached")); - RateLimitException rateLimitException = (RateLimitException) exception; - assertThat(rateLimitException.getDescription(), is("Rate limit reached")); - assertThat(rateLimitException.getError(), is(nullValue())); - assertThat(rateLimitException.getValue("non_existing_key"), is(nullValue())); - assertThat(rateLimitException.getStatusCode(), is(429)); - assertThat(rateLimitException.getLimit(), is(100L)); - assertThat(rateLimitException.getRemaining(), is(10L)); - assertThat(rateLimitException.getReset(), is(5L)); - } - - @Test - public void shouldDefaultRateLimitsHeadersWhenMissing() { - CustomRequest request = new CustomRequest<>(client, server.getBaseUrl(), "GET", listType); - server.rateLimitReachedResponse(-1, -1, -1); - Exception exception = null; - try { - request.execute(); - server.takeRequest(); - } catch (Exception e) { - exception = e; - } - assertThat(exception, is(notNullValue())); - assertThat(exception, is(instanceOf(RateLimitException.class))); - assertThat(exception.getCause(), is(nullValue())); - assertThat(exception.getMessage(), is("Request failed with status code 429: Rate limit reached")); - RateLimitException rateLimitException = (RateLimitException) exception; - assertThat(rateLimitException.getDescription(), is("Rate limit reached")); - assertThat(rateLimitException.getError(), is(nullValue())); - assertThat(rateLimitException.getValue("non_existing_key"), is(nullValue())); - assertThat(rateLimitException.getStatusCode(), is(429)); - assertThat(rateLimitException.getLimit(), is(-1L)); - assertThat(rateLimitException.getRemaining(), is(-1L)); - assertThat(rateLimitException.getReset(), is(-1L)); - } - -} diff --git a/src/test/java/com/auth0/net/EmptyBodyRequestTest.java b/src/test/java/com/auth0/net/EmptyBodyRequestTest.java index 5497384c1..a284bab31 100644 --- a/src/test/java/com/auth0/net/EmptyBodyRequestTest.java +++ b/src/test/java/com/auth0/net/EmptyBodyRequestTest.java @@ -1,14 +1,16 @@ package com.auth0.net; import com.auth0.client.MockServer; +import com.auth0.client.mgmt.SimpleTokenProvider; import com.auth0.json.auth.TokenHolder; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.DefaultHttpClient; +import com.auth0.net.client.HttpMethod; import com.fasterxml.jackson.core.type.TypeReference; -import okhttp3.OkHttpClient; import okhttp3.mockwebserver.RecordedRequest; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import java.util.Map; @@ -21,46 +23,46 @@ public class EmptyBodyRequestTest { private MockServer server; - private OkHttpClient client; + private Auth0HttpClient client; private TypeReference tokenHolderType; - @Before + @BeforeEach public void setUp() throws Exception { server = new MockServer(); - client = new OkHttpClient(); + client = new DefaultHttpClient.Builder().build(); tokenHolderType = new TypeReference() { }; } - @After + @AfterEach public void tearDown() throws Exception { server.stop(); } @Test public void shouldCreateEmptyRequestBody() throws Exception { - EmptyBodyRequest request = new EmptyBodyRequest<>(client, server.getBaseUrl(), "POST", tokenHolderType); + EmptyBodyRequest request = new EmptyBodyRequest<>(client, SimpleTokenProvider.create("apiToken"), server.getBaseUrl(), HttpMethod.POST, tokenHolderType); assertThat(request, is(notNullValue())); server.jsonResponse(AUTH_TOKENS, 200); - request.execute(); + request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest.getMethod(), is("POST")); + assertThat(recordedRequest.getMethod(), is(HttpMethod.POST.toString())); assertThat(recordedRequest.getBodySize(), is(0L)); } @Test public void shouldNotAddParameters() throws Exception { - EmptyBodyRequest request = new EmptyBodyRequest<>(client, server.getBaseUrl(), "POST", tokenHolderType); + EmptyBodyRequest request = new EmptyBodyRequest<>(client, SimpleTokenProvider.create("apiToken"), server.getBaseUrl(), HttpMethod.POST, tokenHolderType); Map mapValue = mock(Map.class); request.addParameter("key", "value"); request.addParameter("map", mapValue); server.jsonResponse(AUTH_TOKENS, 200); - request.execute(); + request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest.getMethod(), is("POST")); + assertThat(recordedRequest.getMethod(), is(HttpMethod.POST.toString())); assertThat(recordedRequest.getBodySize(), is(0L)); } } diff --git a/src/test/java/com/auth0/net/EmptyBodyVoidRequestTest.java b/src/test/java/com/auth0/net/EmptyBodyVoidRequestTest.java new file mode 100644 index 000000000..ba356b36c --- /dev/null +++ b/src/test/java/com/auth0/net/EmptyBodyVoidRequestTest.java @@ -0,0 +1,53 @@ +package com.auth0.net; + +import com.auth0.client.MockServer; +import com.auth0.client.mgmt.TokenProvider; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.DefaultHttpClient; +import com.auth0.net.client.HttpMethod; +import com.fasterxml.jackson.core.type.TypeReference; +import okhttp3.mockwebserver.RecordedRequest; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.concurrent.CompletableFuture; + +import static com.auth0.client.MockServer.AUTH_TOKENS; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; + +public class EmptyBodyVoidRequestTest { + + private Auth0HttpClient client; + private TokenProvider tokenProvider; + private MockServer server; + + @BeforeEach + public void setUp() throws Exception { + client = new DefaultHttpClient.Builder().build(); + server = new MockServer(); + tokenProvider = new TokenProvider() { + @Override + public String getToken() { + return "Bearer abc"; + } + + @Override + public CompletableFuture getTokenAsync() { + return CompletableFuture.completedFuture("Bearer abc"); + } + }; + } + + @Test + public void shouldCreatePOSTRequest() throws Exception { + EmptyBodyVoidRequest request = new EmptyBodyVoidRequest<>(client, tokenProvider, server.getBaseUrl(), HttpMethod.POST, new TypeReference() {}); + assertThat(request, is(notNullValue())); + + server.jsonResponse(AUTH_TOKENS, 200); + Void execute = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + assertThat(recordedRequest.getMethod(), is(HttpMethod.POST.toString())); + assertThat(execute, is(nullValue())); + } +} diff --git a/src/test/java/com/auth0/net/FormBodyRequestTest.java b/src/test/java/com/auth0/net/FormBodyRequestTest.java new file mode 100644 index 000000000..0625e439c --- /dev/null +++ b/src/test/java/com/auth0/net/FormBodyRequestTest.java @@ -0,0 +1,91 @@ +package com.auth0.net; + +import com.auth0.client.MockServer; +import com.auth0.client.mgmt.TokenProvider; +import com.auth0.json.auth.PushedAuthorizationResponse; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.DefaultHttpClient; +import com.auth0.net.client.HttpMethod; +import com.fasterxml.jackson.core.type.TypeReference; +import okhttp3.mockwebserver.RecordedRequest; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.concurrent.CompletableFuture; + +import static com.auth0.client.MockServer.PUSHED_AUTHORIZATION_RESPONSE; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; + +public class FormBodyRequestTest { + private MockServer server; + private Auth0HttpClient client; + private TokenProvider tokenProvider; + + private TypeReference pushedAuthorizationResponseTypeReference; + + @BeforeEach + public void setUp() throws Exception { + server = new MockServer(); + client = new DefaultHttpClient.Builder().withMaxRetries(0).build(); + pushedAuthorizationResponseTypeReference = new TypeReference() { + }; + tokenProvider = new TokenProvider() { + @Override + public String getToken() { + return "xyz"; + } + + @Override + public CompletableFuture getTokenAsync() { + return CompletableFuture.completedFuture("xyz"); + } + }; + } + + @AfterEach + public void tearDown() throws Exception { + server.stop(); + } + + @Test + public void shouldCreatePOSTRequest() throws Exception { + FormBodyRequest request = new FormBodyRequest<>(client, tokenProvider, server.getBaseUrl(), HttpMethod.POST, pushedAuthorizationResponseTypeReference); + assertThat(request, is(notNullValue())); + request.addParameter("audience", "aud"); + request.addParameter("connection", "conn"); + + server.jsonResponse(PUSHED_AUTHORIZATION_RESPONSE, 201); + PushedAuthorizationResponse execute = request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + assertThat(recordedRequest.getMethod(), is(HttpMethod.POST.toString())); + assertThat(execute, is(notNullValue())); + } + + @Test + public void shouldNotOverrideContentTypeHeader() throws Exception { + FormBodyRequest request = new FormBodyRequest<>(client, tokenProvider, server.getBaseUrl(), HttpMethod.POST, pushedAuthorizationResponseTypeReference); + request.addHeader("Content-Type", "plaintext"); + + server.jsonResponse(PUSHED_AUTHORIZATION_RESPONSE, 201); + request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest.getHeader("Content-Type"), containsString("application/x-www-form-urlencoded")); + } + + @Test + public void shouldAddHeaders() throws Exception { + FormBodyRequest request = new FormBodyRequest<>(client, tokenProvider, server.getBaseUrl(), HttpMethod.POST, pushedAuthorizationResponseTypeReference); + request.addHeader("Extra-Info", "this is a test"); + request.addHeader("Authorization", "Bearer my_access_token"); + + server.jsonResponse(PUSHED_AUTHORIZATION_RESPONSE, 200); + request.execute().getBody(); + RecordedRequest recordedRequest = server.takeRequest(); + + assertThat(recordedRequest.getHeader("Extra-Info"), is("this is a test")); + assertThat(recordedRequest.getHeader("Authorization"), is("Bearer xyz")); + } +} diff --git a/src/test/java/com/auth0/net/MultipartRequestTest.java b/src/test/java/com/auth0/net/MultipartRequestTest.java index 72fb4f389..848a8df8b 100644 --- a/src/test/java/com/auth0/net/MultipartRequestTest.java +++ b/src/test/java/com/auth0/net/MultipartRequestTest.java @@ -1,102 +1,109 @@ package com.auth0.net; import com.auth0.client.MockServer; +import com.auth0.client.mgmt.TokenProvider; import com.auth0.exception.APIException; import com.auth0.exception.Auth0Exception; import com.auth0.exception.RateLimitException; import com.auth0.json.auth.TokenHolder; -import com.auth0.net.multipart.FilePart; -import com.auth0.net.multipart.KeyValuePart; -import com.auth0.net.multipart.RecordedMultipartRequest; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.Auth0MultipartRequestBody; +import com.auth0.net.client.DefaultHttpClient; +import com.auth0.net.client.HttpMethod; +import com.auth0.net.client.multipart.FilePart; +import com.auth0.net.client.multipart.KeyValuePart; +import com.auth0.net.client.multipart.RecordedMultipartRequest; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; -import okhttp3.Call; -import okhttp3.MultipartBody; -import okhttp3.OkHttpClient; import okhttp3.mockwebserver.RecordedRequest; import org.hamcrest.Matchers; -import org.junit.*; -import org.junit.rules.ExpectedException; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.util.List; -import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import static com.auth0.AssertsUtil.verifyThrows; import static com.auth0.client.MockServer.*; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; public class MultipartRequestTest { private MockServer server; - private OkHttpClient client; + private Auth0HttpClient client; + private TokenProvider tokenProvider; - @SuppressWarnings("deprecation") - @Rule - public ExpectedException exception = ExpectedException.none(); private TypeReference tokenHolderType; private TypeReference listType; private TypeReference voidType; - @Before + @BeforeEach public void setUp() throws Exception { server = new MockServer(); - client = new OkHttpClient(); + client = new DefaultHttpClient.Builder().withMaxRetries(0).build(); tokenHolderType = new TypeReference() { }; listType = new TypeReference() { }; voidType = new TypeReference() { }; + tokenProvider = new TokenProvider() { + @Override + public String getToken() { + return "xyz"; + } + @Override + public CompletableFuture getTokenAsync() { + return CompletableFuture.completedFuture("xyz"); + } + }; } - @After + @AfterEach public void tearDown() throws Exception { server.stop(); } @Test public void shouldNotSupportGETMethod() { - exception.expect(instanceOf(IllegalArgumentException.class)); - exception.expectMessage("Multipart/form-data requests do not support the GET method."); - MultipartRequest request = new MultipartRequest<>(client, server.getBaseUrl(), "GET", tokenHolderType); + verifyThrows(IllegalArgumentException.class, + () -> new MultipartRequest<>(client, tokenProvider, server.getBaseUrl(), HttpMethod.GET, tokenHolderType), + "Multipart/form-data requests do not support the GET method."); } @Test public void shouldCreatePOSTRequest() throws Exception { - MultipartRequest request = new MultipartRequest<>(client, server.getBaseUrl(), "POST", tokenHolderType); + MultipartRequest request = new MultipartRequest<>(client, tokenProvider, server.getBaseUrl(), HttpMethod.POST, tokenHolderType); assertThat(request, is(notNullValue())); request.addPart("non_empty", "body"); server.jsonResponse(AUTH_TOKENS, 200); - TokenHolder execute = request.execute(); + TokenHolder execute = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest.getMethod(), is("POST")); + assertThat(recordedRequest.getMethod(), is(HttpMethod.POST.toString())); assertThat(execute, is(notNullValue())); } @Test public void shouldAddMultipleParts() throws Exception { - String boundary = UUID.randomUUID().toString(); - MultipartBody.Builder bodyBuilder = new MultipartBody.Builder(boundary); - MultipartRequest request = new MultipartRequest<>(client, server.getBaseUrl(), "POST", new ObjectMapper(), tokenHolderType, bodyBuilder); + Auth0MultipartRequestBody.Builder bodyBuilder = Auth0MultipartRequestBody.newBuilder(); + MultipartRequest request = new MultipartRequest<>(client, tokenProvider, server.getBaseUrl(), HttpMethod.POST, new ObjectMapper(), tokenHolderType); File fileValue = new File(MULTIPART_SAMPLE); request.addPart("keyName", "keyValue"); request.addPart("jsonFile", fileValue, "text/json"); server.jsonResponse(AUTH_TOKENS, 200); - request.execute(); + request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); RecordedMultipartRequest recordedMultipartRequest = new RecordedMultipartRequest(recordedRequest); assertThat(recordedMultipartRequest.getPartsCount(), is(2)); - assertThat(recordedMultipartRequest.getBoundary(), is(boundary)); KeyValuePart formParam = recordedMultipartRequest.getKeyValuePart("keyName"); assertThat(formParam, is(notNullValue())); @@ -112,53 +119,38 @@ public void shouldAddMultipleParts() throws Exception { @Test public void shouldNotOverrideContentTypeHeader() throws Exception { - MultipartBody.Builder bodyBuilder = new MultipartBody.Builder("5c49fdf2"); - MultipartRequest request = new MultipartRequest<>(client, server.getBaseUrl(), "POST", new ObjectMapper(), tokenHolderType, bodyBuilder); + MultipartRequest request = new MultipartRequest<>(client, tokenProvider, server.getBaseUrl(), HttpMethod.POST, new ObjectMapper(), tokenHolderType); request.addPart("non_empty", "body"); request.addHeader("Content-Type", "plaintext"); server.jsonResponse(AUTH_TOKENS, 200); - request.execute(); + request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest.getHeader("Content-Type"), is("multipart/form-data; boundary=5c49fdf2")); + assertThat(recordedRequest.getHeader("Content-Type"), containsString("multipart/form-data;")); } @Test public void shouldAddHeaders() throws Exception { - MultipartRequest request = new MultipartRequest<>(client, server.getBaseUrl(), "POST", tokenHolderType); + MultipartRequest request = new MultipartRequest<>(client, tokenProvider, server.getBaseUrl(), HttpMethod.POST, tokenHolderType); request.addPart("non_empty", "body"); request.addHeader("Extra-Info", "this is a test"); request.addHeader("Authorization", "Bearer my_access_token"); server.jsonResponse(AUTH_TOKENS, 200); - request.execute(); + request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); assertThat(recordedRequest.getHeader("Extra-Info"), is("this is a test")); - assertThat(recordedRequest.getHeader("Authorization"), is("Bearer my_access_token")); - } - - @Test - public void shouldThrowOnExecuteFailure() throws Exception { - exception.expect(Auth0Exception.class); - exception.expectCause(Matchers.instanceOf(IOException.class)); - exception.expectMessage("Failed to execute request"); - - OkHttpClient client = mock(OkHttpClient.class); - Call call = mock(Call.class); - when(client.newCall(any(okhttp3.Request.class))).thenReturn(call); - when(call.execute()).thenThrow(IOException.class); - MultipartRequest request = new MultipartRequest<>(client, server.getBaseUrl(), "POST", voidType); - request.addPart("non_empty", "body"); - request.execute(); + // auth header will be done on the request handling + assertThat(recordedRequest.getHeader("Authorization"), is("Bearer xyz")); } @Test public void shouldThrowOnBodyCreationFailure() { Exception exception = null; try { - MultipartRequest request = new MultipartRequest<>(client, server.getBaseUrl(), "POST", voidType); + MultipartRequest request = new MultipartRequest<>(client, tokenProvider, server.getBaseUrl(), HttpMethod.POST, voidType); request.execute(); } catch (Exception e) { exception = e; @@ -172,10 +164,10 @@ public void shouldThrowOnBodyCreationFailure() { @Test public void shouldParseSuccessfulResponse() throws Exception { - MultipartRequest request = new MultipartRequest<>(client, server.getBaseUrl(), "POST", tokenHolderType); + MultipartRequest request = new MultipartRequest<>(client, tokenProvider, server.getBaseUrl(), HttpMethod.POST, tokenHolderType); request.addPart("non_empty", "body"); server.jsonResponse(AUTH_TOKENS, 200); - TokenHolder response = request.execute(); + TokenHolder response = request.execute().getBody(); server.takeRequest(); assertThat(response, is(notNullValue())); @@ -188,12 +180,12 @@ public void shouldParseSuccessfulResponse() throws Exception { @Test public void shouldThrowOnParseInvalidSuccessfulResponse() throws Exception { - MultipartRequest request = new MultipartRequest<>(client, server.getBaseUrl(), "POST", listType); + MultipartRequest request = new MultipartRequest<>(client, tokenProvider, server.getBaseUrl(), HttpMethod.POST, listType); request.addPart("non_empty", "body"); server.jsonResponse(AUTH_TOKENS, 200); Exception exception = null; try { - request.execute(); + request.execute().getBody(); server.takeRequest(); } catch (Exception e) { exception = e; @@ -210,12 +202,12 @@ public void shouldThrowOnParseInvalidSuccessfulResponse() throws Exception { @Test public void shouldParseJSONErrorResponseWithErrorDescription() throws Exception { - MultipartRequest request = new MultipartRequest<>(client, server.getBaseUrl(), "POST", listType); + MultipartRequest request = new MultipartRequest<>(client, tokenProvider, server.getBaseUrl(), HttpMethod.POST, listType); request.addPart("non_empty", "body"); server.jsonResponse(AUTH_ERROR_WITH_ERROR_DESCRIPTION, 400); Exception exception = null; try { - request.execute(); + request.execute().getBody(); server.takeRequest(); } catch (Exception e) { exception = e; @@ -232,12 +224,12 @@ public void shouldParseJSONErrorResponseWithErrorDescription() throws Exception @Test public void shouldParseJSONErrorResponseWithError() throws Exception { - MultipartRequest request = new MultipartRequest<>(client, server.getBaseUrl(), "POST", listType); + MultipartRequest request = new MultipartRequest<>(client, tokenProvider, server.getBaseUrl(), HttpMethod.POST, listType); request.addPart("non_empty", "body"); server.jsonResponse(AUTH_ERROR_WITH_ERROR, 400); Exception exception = null; try { - request.execute(); + request.execute().getBody(); server.takeRequest(); } catch (Exception e) { exception = e; @@ -254,12 +246,12 @@ public void shouldParseJSONErrorResponseWithError() throws Exception { @Test public void shouldParseJSONErrorResponseWithDescriptionAndExtraProperties() throws Exception { - MultipartRequest request = new MultipartRequest<>(client, server.getBaseUrl(), "POST", listType); + MultipartRequest request = new MultipartRequest<>(client, tokenProvider, server.getBaseUrl(), HttpMethod.POST, listType); request.addPart("non_empty", "body"); server.jsonResponse(AUTH_ERROR_WITH_DESCRIPTION_AND_EXTRA_PROPERTIES, 400); Exception exception = null; try { - request.execute(); + request.execute().getBody(); server.takeRequest(); } catch (Exception e) { exception = e; @@ -278,12 +270,12 @@ public void shouldParseJSONErrorResponseWithDescriptionAndExtraProperties() thro @Test public void shouldParseJSONErrorResponseWithDescription() throws Exception { - MultipartRequest request = new MultipartRequest<>(client, server.getBaseUrl(), "POST", listType); + MultipartRequest request = new MultipartRequest<>(client, tokenProvider, server.getBaseUrl(), HttpMethod.POST, listType); request.addPart("non_empty", "body"); server.jsonResponse(AUTH_ERROR_WITH_DESCRIPTION, 400); Exception exception = null; try { - request.execute(); + request.execute().getBody(); server.takeRequest(); } catch (Exception e) { exception = e; @@ -300,12 +292,12 @@ public void shouldParseJSONErrorResponseWithDescription() throws Exception { @Test public void shouldParseJSONErrorResponseWithMessage() throws Exception { - MultipartRequest request = new MultipartRequest<>(client, server.getBaseUrl(), "POST", listType); + MultipartRequest request = new MultipartRequest<>(client, tokenProvider, server.getBaseUrl(), HttpMethod.POST, listType); request.addPart("non_empty", "body"); server.jsonResponse(MGMT_ERROR_WITH_MESSAGE, 400); Exception exception = null; try { - request.execute(); + request.execute().getBody(); server.takeRequest(); } catch (Exception e) { exception = e; @@ -322,12 +314,12 @@ public void shouldParseJSONErrorResponseWithMessage() throws Exception { @Test public void shouldParsePlainTextErrorResponse() throws Exception { - MultipartRequest request = new MultipartRequest<>(client, server.getBaseUrl(), "POST", listType); + MultipartRequest request = new MultipartRequest<>(client, tokenProvider, server.getBaseUrl(), HttpMethod.POST, listType); request.addPart("non_empty", "body"); server.textResponse(AUTH_ERROR_PLAINTEXT, 400); Exception exception = null; try { - request.execute(); + request.execute().getBody(); server.takeRequest(); } catch (Exception e) { exception = e; @@ -344,13 +336,13 @@ public void shouldParsePlainTextErrorResponse() throws Exception { } @Test - public void shouldParseRateLimitsHeaders() { - MultipartRequest request = new MultipartRequest<>(client, server.getBaseUrl(), "POST", listType); + public void shouldParseRateLimitsHeaders() throws Exception { + MultipartRequest request = new MultipartRequest<>(client, tokenProvider, server.getBaseUrl(), HttpMethod.POST, listType); request.addPart("non_empty", "body"); server.rateLimitReachedResponse(100, 10, 5); Exception exception = null; try { - request.execute(); + request.execute().getBody(); server.takeRequest(); } catch (Exception e) { exception = e; @@ -370,13 +362,58 @@ public void shouldParseRateLimitsHeaders() { } @Test - public void shouldDefaultRateLimitsHeadersWhenMissing() { - MultipartRequest request = new MultipartRequest<>(client, server.getBaseUrl(), "POST", listType); + public void shouldParseRateLimitsWithAllHeaders() throws Exception { + MultipartRequest request = new MultipartRequest<>(client, tokenProvider, server.getBaseUrl(), HttpMethod.POST, listType); + request.addPart("non_empty", "body"); + server.rateLimitReachedResponse(100, 10, 5, getTokenQuotaString(), getTokenQuotaString(), 1000); + Exception exception = null; + try { + request.execute().getBody(); + server.takeRequest(); + } catch (Exception e) { + exception = e; + } + assertThat(exception, is(notNullValue())); + assertThat(exception, is(instanceOf(RateLimitException.class))); + assertThat(exception.getCause(), is(nullValue())); + assertThat(exception.getMessage(), is("Request failed with status code 429: Rate limit reached")); + RateLimitException rateLimitException = (RateLimitException) exception; + assertThat(rateLimitException.getDescription(), is("Rate limit reached")); + assertThat(rateLimitException.getError(), is(nullValue())); + assertThat(rateLimitException.getValue("non_existing_key"), is(nullValue())); + assertThat(rateLimitException.getStatusCode(), is(429)); + assertThat(rateLimitException.getLimit(), is(100L)); + assertThat(rateLimitException.getRemaining(), is(10L)); + assertThat(rateLimitException.getReset(), is(5L)); + assertThat(rateLimitException.getRetryAfter(), is(1000L)); + assertThat(rateLimitException.getClientQuotaLimit(), is(notNullValue())); + assertThat(rateLimitException.getClientQuotaLimit().getPerHour(), is(notNullValue())); + assertThat(rateLimitException.getClientQuotaLimit().getPerDay(), is(notNullValue())); + assertThat(rateLimitException.getClientQuotaLimit().getPerHour().getQuota(), is(100)); + assertThat(rateLimitException.getClientQuotaLimit().getPerHour().getRemaining(), is(80)); + assertThat(rateLimitException.getClientQuotaLimit().getPerHour().getResetAfter(), is(3600)); + assertThat(rateLimitException.getClientQuotaLimit().getPerDay().getQuota(), is(100)); + assertThat(rateLimitException.getClientQuotaLimit().getPerDay().getRemaining(), is(90)); + assertThat(rateLimitException.getClientQuotaLimit().getPerDay().getResetAfter(), is(86400)); + assertThat(rateLimitException.getOrganizationQuotaLimit(), is(notNullValue())); + assertThat(rateLimitException.getOrganizationQuotaLimit().getPerHour(), is(notNullValue())); + assertThat(rateLimitException.getOrganizationQuotaLimit().getPerDay(), is(notNullValue())); + assertThat(rateLimitException.getOrganizationQuotaLimit().getPerHour().getQuota(), is(100)); + assertThat(rateLimitException.getOrganizationQuotaLimit().getPerHour().getRemaining(), is(80)); + assertThat(rateLimitException.getOrganizationQuotaLimit().getPerHour().getResetAfter(), is(3600)); + assertThat(rateLimitException.getOrganizationQuotaLimit().getPerDay().getQuota(), is(100)); + assertThat(rateLimitException.getOrganizationQuotaLimit().getPerDay().getRemaining(), is(90)); + assertThat(rateLimitException.getOrganizationQuotaLimit().getPerDay().getResetAfter(), is(86400)); + } + + @Test + public void shouldDefaultRateLimitsHeadersWhenMissing() throws Exception { + MultipartRequest request = new MultipartRequest<>(client, tokenProvider, server.getBaseUrl(), HttpMethod.POST, listType); request.addPart("non_empty", "body"); server.rateLimitReachedResponse(-1, -1, -1); Exception exception = null; try { - request.execute(); + request.execute().getBody(); server.takeRequest(); } catch (Exception e) { exception = e; @@ -393,6 +430,29 @@ public void shouldDefaultRateLimitsHeadersWhenMissing() { assertThat(rateLimitException.getLimit(), is(-1L)); assertThat(rateLimitException.getRemaining(), is(-1L)); assertThat(rateLimitException.getReset(), is(-1L)); + assertThat(rateLimitException.getClientQuotaLimit(), Matchers.is(nullValue())); + assertThat(rateLimitException.getOrganizationQuotaLimit(), Matchers.is(nullValue())); } + public String getTokenQuotaString() { + TokenQuotaLimit perHourLimit = new TokenQuotaLimit(100, 80, 3600); + TokenQuotaLimit perDayLimit = new TokenQuotaLimit(100, 90, 86400); + + StringBuilder builder = new StringBuilder(); + + if (perHourLimit != null) { + builder.append(String.format("b=per_hour;q=%d;r=%d;t=%d", + perHourLimit.getQuota(), perHourLimit.getRemaining(), perHourLimit.getResetAfter())); + } + + if (perDayLimit != null) { + if (builder.length() > 0) { + builder.append(","); + } + builder.append(String.format("b=per_day;q=%d;r=%d;t=%d", + perDayLimit.getQuota(), perDayLimit.getRemaining(), perDayLimit.getResetAfter())); + } + + return builder.toString(); + } } diff --git a/src/test/java/com/auth0/net/RateLimitInterceptorTest.java b/src/test/java/com/auth0/net/RateLimitInterceptorTest.java index 5e4ea3526..f05ea72be 100644 --- a/src/test/java/com/auth0/net/RateLimitInterceptorTest.java +++ b/src/test/java/com/auth0/net/RateLimitInterceptorTest.java @@ -1,18 +1,22 @@ package com.auth0.net; +import com.auth0.exception.Auth0Exception; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; import okhttp3.mockwebserver.MockResponse; import okhttp3.mockwebserver.MockWebServer; import okhttp3.mockwebserver.RecordedRequest; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; +import okhttp3.mockwebserver.SocketPolicy; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import java.time.Duration; import java.util.ArrayList; import java.util.List; +import static com.auth0.AssertsUtil.verifyThrows; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.closeTo; @@ -22,12 +26,12 @@ public class RateLimitInterceptorTest { MockWebServer server = new MockWebServer(); - @Before + @BeforeEach public void setUp() throws Exception { server.start(); } - @After + @AfterEach public void tearDown() throws Exception { server.shutdown(); } @@ -104,9 +108,7 @@ public void shouldReturnResponseWhenMaxRetriesHit() throws Exception { int index = 0; for (int i = 0; i < maxRetries + 1; i++) { - System.out.println("about to take request " + i); index = server.takeRequest().getSequenceNumber(); - System.out.println("took request " + i); } assertThat(response.code(), is(429)); @@ -175,4 +177,22 @@ public void shouldBackOffOnRetries() throws Exception { assertThat(retryTimings.get(5), greaterThan(retryTimings.get(2))); } + @Test + public void shouldThrowAuth0Exception() { + OkHttpClient client = new OkHttpClient.Builder() + .addInterceptor(new RateLimitInterceptor(3)) + .readTimeout(Duration.ofSeconds(1)) + .build(); + + server.enqueue(new MockResponse().setSocketPolicy(SocketPolicy.NO_RESPONSE)); + + okhttp3.Request request = new Request.Builder() + .get() + .url(server.url("/")) + .build(); + + Auth0Exception e = verifyThrows(Auth0Exception.class, + () -> client.newCall(request).execute(), + "Failed to execute request"); + } } diff --git a/src/test/java/com/auth0/net/RequestTest.java b/src/test/java/com/auth0/net/RequestTest.java deleted file mode 100644 index bfd0e2dd6..000000000 --- a/src/test/java/com/auth0/net/RequestTest.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.auth0.net; - -import com.auth0.exception.Auth0Exception; -import org.junit.Test; -import static org.junit.Assert.assertThrows; - -public class RequestTest { - - @Test - public void defaultImplementationShouldThrow() { - assertThrows("executeAsync", - UnsupportedOperationException.class, - new Request() { - @Override - public String execute() throws Auth0Exception { - return null; - } - }::executeAsync); - } -} diff --git a/src/test/java/com/auth0/net/CreateUserRequestTest.java b/src/test/java/com/auth0/net/SignUpRequestTest.java similarity index 69% rename from src/test/java/com/auth0/net/CreateUserRequestTest.java rename to src/test/java/com/auth0/net/SignUpRequestTest.java index 9504486bf..754b6edc2 100644 --- a/src/test/java/com/auth0/net/CreateUserRequestTest.java +++ b/src/test/java/com/auth0/net/SignUpRequestTest.java @@ -2,45 +2,47 @@ import com.auth0.client.MockServer; import com.auth0.json.auth.CreatedUser; -import okhttp3.OkHttpClient; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.DefaultHttpClient; +import com.auth0.net.client.HttpMethod; import okhttp3.mockwebserver.RecordedRequest; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import java.util.HashMap; import java.util.Map; import static com.auth0.client.MockServer.*; -import static org.hamcrest.Matchers.*; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; -public class CreateUserRequestTest { +public class SignUpRequestTest { - private OkHttpClient client; + private Auth0HttpClient client; private MockServer server; - @Before + @BeforeEach public void setUp() throws Exception { - client = new OkHttpClient(); + client = new DefaultHttpClient.Builder().build(); server = new MockServer(); } @Test public void shouldCreatePOSTRequest() throws Exception { - CreateUserRequest request = new CreateUserRequest(client, server.getBaseUrl()); + SignUpRequest request = new SignUpRequest(client, server.getBaseUrl()); assertThat(request, is(notNullValue())); request.addParameter("non_empty", "body"); server.jsonResponse(AUTH_SIGN_UP, 200); - CreatedUser execute = request.execute(); + CreatedUser execute = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest.getMethod(), is("POST")); + assertThat(recordedRequest.getMethod(), is(HttpMethod.POST.toString())); assertThat(execute, is(notNullValue())); } @Test public void shouldSetSignUpCustomFields() throws Exception { - CreateUserRequest request = new CreateUserRequest(client, server.getBaseUrl()); + SignUpRequest request = new SignUpRequest(client, server.getBaseUrl()); assertThat(request, is(notNullValue())); Map customFields = new HashMap<>(); customFields.put("name", "john"); @@ -48,7 +50,7 @@ public void shouldSetSignUpCustomFields() throws Exception { request.setCustomFields(customFields); server.jsonResponse(AUTH_TOKENS, 200); - request.execute(); + request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); Map values = bodyFromRequest(recordedRequest); @@ -60,4 +62,4 @@ public void shouldSetSignUpCustomFields() throws Exception { } -} \ No newline at end of file +} diff --git a/src/test/java/com/auth0/net/TelemetryInterceptorTest.java b/src/test/java/com/auth0/net/TelemetryInterceptorTest.java index ae866e1a5..8fd139457 100644 --- a/src/test/java/com/auth0/net/TelemetryInterceptorTest.java +++ b/src/test/java/com/auth0/net/TelemetryInterceptorTest.java @@ -5,8 +5,8 @@ import okhttp3.mockwebserver.MockResponse; import okhttp3.mockwebserver.MockWebServer; import okhttp3.mockwebserver.RecordedRequest; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.nullValue; @@ -17,7 +17,7 @@ public class TelemetryInterceptorTest { private Telemetry telemetry; - @Before + @BeforeEach public void setUp() { telemetry = mock(Telemetry.class); when(telemetry.getValue()).thenReturn("ClientInfo"); diff --git a/src/test/java/com/auth0/net/TelemetryTest.java b/src/test/java/com/auth0/net/TelemetryTest.java index f3dec4d80..70f986232 100644 --- a/src/test/java/com/auth0/net/TelemetryTest.java +++ b/src/test/java/com/auth0/net/TelemetryTest.java @@ -2,17 +2,24 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Test; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; import java.nio.charset.StandardCharsets; import java.util.Base64; import java.util.Map; -import static org.hamcrest.Matchers.*; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; public class TelemetryTest { + @BeforeAll + public static void setup() { + //Set so that Telemetry object doesn't use different Java versions while testing which will create different Base64 encoded value + System.setProperty("java.specification.version", "1.8"); + } + @Test public void shouldReturnBasicTelemetryBase64Value() throws Exception { Telemetry telemetry = new Telemetry("auth0-java", "1.0.0"); diff --git a/src/test/java/com/auth0/net/TokenRequestTest.java b/src/test/java/com/auth0/net/TokenRequestTest.java index d81edc840..a85c52d29 100644 --- a/src/test/java/com/auth0/net/TokenRequestTest.java +++ b/src/test/java/com/auth0/net/TokenRequestTest.java @@ -2,31 +2,33 @@ import com.auth0.client.MockServer; import com.auth0.json.auth.TokenHolder; -import okhttp3.OkHttpClient; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.DefaultHttpClient; +import com.auth0.net.client.HttpMethod; import okhttp3.mockwebserver.RecordedRequest; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import java.util.Map; import static com.auth0.client.MockServer.AUTH_TOKENS; import static com.auth0.client.MockServer.bodyFromRequest; -import static org.hamcrest.Matchers.*; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; public class TokenRequestTest { - private OkHttpClient client; + private Auth0HttpClient client; private MockServer server; - @Before + @BeforeEach public void setUp() throws Exception { - client = new OkHttpClient(); + client = new DefaultHttpClient.Builder().build(); server = new MockServer(); } - @After + @AfterEach public void tearDown() throws Exception { server.stop(); } @@ -38,9 +40,9 @@ public void shouldCreateRequest() throws Exception { assertThat(request, is(notNullValue())); server.jsonResponse(AUTH_TOKENS, 200); - TokenHolder response = request.execute(); + TokenHolder response = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest.getMethod(), is("POST")); + assertThat(recordedRequest.getMethod(), is(HttpMethod.POST.toString())); assertThat(response, is(notNullValue())); } @@ -51,7 +53,7 @@ public void shouldSetAudience() throws Exception { request.setAudience("https://myapi.auth0.com/users"); server.jsonResponse(AUTH_TOKENS, 200); - request.execute(); + request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); Map values = bodyFromRequest(recordedRequest); assertThat(values, hasEntry("audience", "https://myapi.auth0.com/users")); @@ -64,7 +66,7 @@ public void shouldSetScope() throws Exception { request.setScope("email profile photos"); server.jsonResponse(AUTH_TOKENS, 200); - request.execute(); + request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); Map values = bodyFromRequest(recordedRequest); assertThat(values, hasEntry("scope", "email profile photos")); @@ -77,7 +79,7 @@ public void shouldSetRealm() throws Exception { request.setRealm("dbconnection"); server.jsonResponse(AUTH_TOKENS, 200); - request.execute(); + request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); Map values = bodyFromRequest(recordedRequest); assertThat(values, hasEntry("realm", "dbconnection")); diff --git a/src/test/java/com/auth0/net/VoidRequestTest.java b/src/test/java/com/auth0/net/VoidRequestTest.java index 1b912c956..34743b527 100644 --- a/src/test/java/com/auth0/net/VoidRequestTest.java +++ b/src/test/java/com/auth0/net/VoidRequestTest.java @@ -1,48 +1,64 @@ package com.auth0.net; import com.auth0.client.MockServer; -import okhttp3.OkHttpClient; +import com.auth0.client.mgmt.TokenProvider; +import com.auth0.net.client.Auth0HttpClient; +import com.auth0.net.client.DefaultHttpClient; +import com.auth0.net.client.HttpMethod; import okhttp3.mockwebserver.RecordedRequest; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.concurrent.CompletableFuture; import static com.auth0.client.MockServer.AUTH_TOKENS; -import static org.hamcrest.Matchers.*; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; public class VoidRequestTest { - private OkHttpClient client; + private Auth0HttpClient client; + private TokenProvider tokenProvider; private MockServer server; - @Before + @BeforeEach public void setUp() throws Exception { - client = new OkHttpClient(); + client = new DefaultHttpClient.Builder().build(); server = new MockServer(); + tokenProvider = new TokenProvider() { + @Override + public String getToken() { + return "Bearer xyz"; + } + + @Override + public CompletableFuture getTokenAsync() { + return CompletableFuture.completedFuture("Bearer xyz"); + } + }; } @Test public void shouldCreateGETRequest() throws Exception { - VoidRequest request = new VoidRequest(client, server.getBaseUrl(), "GET"); + VoidRequest request = new VoidRequest(client, tokenProvider, server.getBaseUrl(), HttpMethod.GET); assertThat(request, is(notNullValue())); server.jsonResponse(AUTH_TOKENS, 200); - Void execute = request.execute(); + Void execute = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest.getMethod(), is("GET")); + assertThat(recordedRequest.getMethod(), is(HttpMethod.GET.toString())); assertThat(execute, is(nullValue())); } @Test public void shouldCreatePOSTRequest() throws Exception { - VoidRequest request = new VoidRequest(client, server.getBaseUrl(), "POST"); + VoidRequest request = new VoidRequest(client, tokenProvider, server.getBaseUrl(), HttpMethod.POST); assertThat(request, is(notNullValue())); request.addParameter("non_empty", "body"); server.jsonResponse(AUTH_TOKENS, 200); - Void execute = request.execute(); + Void execute = request.execute().getBody(); RecordedRequest recordedRequest = server.takeRequest(); - assertThat(recordedRequest.getMethod(), is("POST")); + assertThat(recordedRequest.getMethod(), is(HttpMethod.POST.toString())); assertThat(execute, is(nullValue())); } - -} \ No newline at end of file +} diff --git a/src/test/java/com/auth0/net/client/Auth0HttpRequestTest.java b/src/test/java/com/auth0/net/client/Auth0HttpRequestTest.java new file mode 100644 index 000000000..5feae933e --- /dev/null +++ b/src/test/java/com/auth0/net/client/Auth0HttpRequestTest.java @@ -0,0 +1,26 @@ +package com.auth0.net.client; + +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +public class Auth0HttpRequestTest { + + @Test + public void headersAreDefensive() { + Map headers = new HashMap<>(); + headers.put("name", "value"); + + Auth0HttpRequest request = Auth0HttpRequest.newBuilder("url", HttpMethod.POST) + .withHeaders(headers) + .build(); + + headers.put("name", "UPDATED"); + + assertThat(request.getHeaders().get("name"), is("value")); + } +} diff --git a/src/test/java/com/auth0/net/client/Auth0HttpResponseTest.java b/src/test/java/com/auth0/net/client/Auth0HttpResponseTest.java new file mode 100644 index 000000000..fa922f781 --- /dev/null +++ b/src/test/java/com/auth0/net/client/Auth0HttpResponseTest.java @@ -0,0 +1,26 @@ +package com.auth0.net.client; + +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +public class Auth0HttpResponseTest { + + @Test + public void headersAreDefensive() { + Map headers = new HashMap<>(); + headers.put("name", "value"); + + Auth0HttpResponse response = Auth0HttpResponse.newBuilder() + .withHeaders(headers) + .build(); + + headers.put("name", "UPDATED"); + + assertThat(response.getHeaders().get("name"), is("value")); + } +} diff --git a/src/test/java/com/auth0/net/client/DefaultHttpClientTest.java b/src/test/java/com/auth0/net/client/DefaultHttpClientTest.java new file mode 100644 index 000000000..a9f1e7e7a --- /dev/null +++ b/src/test/java/com/auth0/net/client/DefaultHttpClientTest.java @@ -0,0 +1,944 @@ +package com.auth0.net.client; + +import com.auth0.client.LoggingOptions; +import com.auth0.client.ProxyOptions; +import com.auth0.net.RateLimitInterceptor; +import com.auth0.net.TelemetryInterceptor; +import okhttp3.*; +import okhttp3.logging.HttpLoggingInterceptor; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; +import okhttp3.mockwebserver.RecordedRequest; +import okhttp3.mockwebserver.SocketPolicy; +import okio.Buffer; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import java.io.IOException; +import java.net.Proxy; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + +import static com.auth0.AssertsUtil.verifyThrows; +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.isA; +import static org.hamcrest.Matchers.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +public class DefaultHttpClientTest { + + private MockWebServer server; + + @BeforeEach + public void setUp() throws Exception { + server = new MockWebServer(); + server.start(); + } + + @AfterEach + public void tearDown() throws Exception { + server.shutdown(); + } + + @Test + public void makesGetRequest() throws Exception { + Auth0HttpRequest request = Auth0HttpRequest.newBuilder(server.url("/users/2").toString(), HttpMethod.GET) + .withHeaders(Collections.singletonMap("foo", "bar")) + .build(); + + DefaultHttpClient client = new DefaultHttpClient(new OkHttpClient()); + String responseBody = "{\"id\":\"123\", \"name\":\"timmy\"}"; + MockResponse mockResponse = new MockResponse() + .setResponseCode(200) + .setHeader("fiz", "bang") + .setBody(responseBody); + + server.enqueue(mockResponse); + + Auth0HttpResponse response = client.sendRequest(request); + RecordedRequest madeRequest = server.takeRequest(); + + assertThat(madeRequest.getPath(), is("/users/2")); + assertThat(madeRequest.getHeader("foo"), is("bar")); + assertThat(madeRequest.getMethod(), is("GET")); + + assertThat(response.getCode(), is(200)); + assertThat(response.isSuccessful(), is(true)); + assertThat(response.getBody(), is(responseBody)); + assertThat(response.getHeader("fiz"), is("bang")); + } + + @Test + public void makesAsyncGetRequest() throws Exception { + Auth0HttpRequest request = Auth0HttpRequest.newBuilder(server.url("/users/2").toString(), HttpMethod.GET) + .withHeaders(Collections.singletonMap("foo", "bar")) + .build(); + + DefaultHttpClient client = new DefaultHttpClient(new OkHttpClient()); + String responseBody = "{\"id\":\"123\", \"name\":\"timmy\"}"; + MockResponse mockResponse = new MockResponse() + .setResponseCode(200) + .setHeader("fiz", "bang") + .setBody(responseBody); + + server.enqueue(mockResponse); + + CompletableFuture response = client.sendRequestAsync(request); + RecordedRequest madeRequest = server.takeRequest(); + + assertThat(madeRequest.getPath(), is("/users/2")); + assertThat(madeRequest.getHeader("foo"), is("bar")); + assertThat(madeRequest.getMethod(), is("GET")); + + assertThat(response.get().getCode(), is(200)); + assertThat(response.get().isSuccessful(), is(true)); + assertThat(response.get().getBody(), is(responseBody)); + assertThat(response.get().getHeader("fiz"), is("bang")); + } + + + @Test + public void makesPostRequest() throws Exception { + Auth0HttpRequest request = Auth0HttpRequest.newBuilder(server.url("/users/2").toString(), HttpMethod.POST) + .withHeaders(Collections.singletonMap("foo", "bar")) + .withBody(HttpRequestBody.create( + "application/json", + "{\"id\":\"123\", \"name\":\"timmy\"}".getBytes(StandardCharsets.UTF_8))) + .build(); + + DefaultHttpClient client = new DefaultHttpClient(new OkHttpClient()); + String responseBody = "{\"id\":\"123\", \"name\":\"timmy\"}"; + MockResponse mockResponse = new MockResponse() + .setResponseCode(201) + .setHeader("fiz", "bang") + .setBody(responseBody); + + server.enqueue(mockResponse); + + Auth0HttpResponse response = client.sendRequest(request); + RecordedRequest madeRequest = server.takeRequest(); + + assertThat(madeRequest.getPath(), is("/users/2")); + assertThat(madeRequest.getHeader("foo"), is("bar")); + assertThat(madeRequest.getMethod(), is("POST")); + + assertThat(response.getCode(), is(201)); + assertThat(response.isSuccessful(), is(true)); + assertThat(response.getBody(), is(responseBody)); + assertThat(response.getHeader("fiz"), is("bang")); + } + + @Test + public void makesAsyncPostRequest() throws Exception { + Auth0HttpRequest request = Auth0HttpRequest.newBuilder(server.url("/users/2").toString(), HttpMethod.POST) + .withHeaders(Collections.singletonMap("foo", "bar")) + .withBody(HttpRequestBody.create( + "application/json", + "{\"id\":\"123\", \"name\":\"timmy\"}".getBytes(StandardCharsets.UTF_8))) + .build(); + + DefaultHttpClient client = new DefaultHttpClient(new OkHttpClient()); + String responseBody = "{\"id\":\"123\", \"name\":\"timmy\"}"; + MockResponse mockResponse = new MockResponse() + .setResponseCode(201) + .setHeader("fiz", "bang") + .setBody(responseBody); + + server.enqueue(mockResponse); + + CompletableFuture response = client.sendRequestAsync(request); + RecordedRequest madeRequest = server.takeRequest(); + + assertThat(madeRequest.getPath(), is("/users/2")); + assertThat(madeRequest.getHeader("foo"), is("bar")); + assertThat(madeRequest.getMethod(), is("POST")); + + assertThat(response.get().getCode(), is(201)); + assertThat(response.get().isSuccessful(), is(true)); + assertThat(response.get().getBody(), is(responseBody)); + assertThat(response.get().getHeader("fiz"), is("bang")); + } + + @Test + public void makesPatchRequest() throws Exception { + Auth0HttpRequest request = Auth0HttpRequest.newBuilder(server.url("/users/2").toString(), HttpMethod.PATCH) + .withHeaders(Collections.singletonMap("foo", "bar")) + .withBody(HttpRequestBody.create( + "application/json", + "{\"id\":\"123\", \"name\":\"timmy\"}".getBytes(StandardCharsets.UTF_8))) + .build(); + + DefaultHttpClient client = new DefaultHttpClient(new OkHttpClient()); + MockResponse mockResponse = new MockResponse() + .setResponseCode(204) + .setHeader("fiz", "bang"); + + server.enqueue(mockResponse); + + Auth0HttpResponse response = client.sendRequest(request); + RecordedRequest madeRequest = server.takeRequest(); + + assertThat(madeRequest.getPath(), is("/users/2")); + assertThat(madeRequest.getHeader("foo"), is("bar")); + assertThat(madeRequest.getMethod(), is("PATCH")); + + assertThat(response.getCode(), is(204)); + assertThat(response.isSuccessful(), is(true)); + assertThat(response.getHeader("fiz"), is("bang")); + } + + @Test + public void makesAsyncPatchRequest() throws Exception { + Auth0HttpRequest request = Auth0HttpRequest.newBuilder(server.url("/users/2").toString(), HttpMethod.PATCH) + .withHeaders(Collections.singletonMap("foo", "bar")) + .withBody(HttpRequestBody.create( + "application/json", + "{\"id\":\"123\", \"name\":\"timmy\"}".getBytes(StandardCharsets.UTF_8))) + .build(); + + DefaultHttpClient client = new DefaultHttpClient(new OkHttpClient()); + MockResponse mockResponse = new MockResponse() + .setResponseCode(204) + .setHeader("fiz", "bang"); + + server.enqueue(mockResponse); + + CompletableFuture response = client.sendRequestAsync(request); + RecordedRequest madeRequest = server.takeRequest(); + + assertThat(madeRequest.getPath(), is("/users/2")); + assertThat(madeRequest.getHeader("foo"), is("bar")); + assertThat(madeRequest.getMethod(), is("PATCH")); + + assertThat(response.get().getCode(), is(204)); + assertThat(response.get().isSuccessful(), is(true)); + assertThat(response.get().getHeader("fiz"), is("bang")); + } + + @Test + public void makesPutRequest() throws Exception { + Auth0HttpRequest request = Auth0HttpRequest.newBuilder(server.url("/users/2").toString(), HttpMethod.PUT) + .withHeaders(Collections.singletonMap("foo", "bar")) + .withBody(HttpRequestBody.create( + "application/json", + "{\"id\":\"123\", \"name\":\"timmy\"}".getBytes(StandardCharsets.UTF_8))) + .build(); + + DefaultHttpClient client = new DefaultHttpClient(new OkHttpClient()); + MockResponse mockResponse = new MockResponse() + .setResponseCode(204) + .setHeader("fiz", "bang"); + + server.enqueue(mockResponse); + + Auth0HttpResponse response = client.sendRequest(request); + RecordedRequest madeRequest = server.takeRequest(); + + assertThat(madeRequest.getPath(), is("/users/2")); + assertThat(madeRequest.getHeader("foo"), is("bar")); + assertThat(madeRequest.getMethod(), is("PUT")); + + assertThat(response.getCode(), is(204)); + assertThat(response.isSuccessful(), is(true)); + assertThat(response.getHeader("fiz"), is("bang")); + } + + @Test + public void makesAsyncPutRequest() throws Exception { + Auth0HttpRequest request = Auth0HttpRequest.newBuilder(server.url("/users/2").toString(), HttpMethod.PUT) + .withHeaders(Collections.singletonMap("foo", "bar")) + .withBody(HttpRequestBody.create( + "application/json", + "{\"id\":\"123\", \"name\":\"timmy\"}".getBytes(StandardCharsets.UTF_8))) + .build(); + + DefaultHttpClient client = new DefaultHttpClient(new OkHttpClient()); + MockResponse mockResponse = new MockResponse() + .setResponseCode(204) + .setHeader("fiz", "bang"); + + server.enqueue(mockResponse); + + CompletableFuture response = client.sendRequestAsync(request); + RecordedRequest madeRequest = server.takeRequest(); + + assertThat(madeRequest.getPath(), is("/users/2")); + assertThat(madeRequest.getHeader("foo"), is("bar")); + assertThat(madeRequest.getMethod(), is("PUT")); + + assertThat(response.get().getCode(), is(204)); + assertThat(response.get().isSuccessful(), is(true)); + assertThat(response.get().getHeader("fiz"), is("bang")); + } + + @Test + public void makesDeleteRequest() throws Exception { + Auth0HttpRequest request = Auth0HttpRequest.newBuilder(server.url("/users/2").toString(), HttpMethod.DELETE) + .withHeaders(Collections.singletonMap("foo", "bar")) + .build(); + + DefaultHttpClient client = new DefaultHttpClient(new OkHttpClient()); + String responseBody = "{\"id\":\"123\", \"name\":\"timmy\"}"; + MockResponse mockResponse = new MockResponse() + .setResponseCode(202) + .setHeader("fiz", "bang") + .setBody(responseBody); + + server.enqueue(mockResponse); + + Auth0HttpResponse response = client.sendRequest(request); + RecordedRequest madeRequest = server.takeRequest(); + + assertThat(madeRequest.getPath(), is("/users/2")); + assertThat(madeRequest.getHeader("foo"), is("bar")); + assertThat(madeRequest.getMethod(), is("DELETE")); + + assertThat(response.getCode(), is(202)); + assertThat(response.isSuccessful(), is(true)); + assertThat(response.getBody(), is(responseBody)); + assertThat(response.getHeader("fiz"), is("bang")); + } + + @Test + public void makesAsyncDeleteRequest() throws Exception { + Auth0HttpRequest request = Auth0HttpRequest.newBuilder(server.url("/users/2").toString(), HttpMethod.DELETE) + .withHeaders(Collections.singletonMap("foo", "bar")) + .build(); + + DefaultHttpClient client = new DefaultHttpClient(new OkHttpClient()); + String responseBody = "{\"id\":\"123\", \"name\":\"timmy\"}"; + MockResponse mockResponse = new MockResponse() + .setResponseCode(202) + .setHeader("fiz", "bang") + .setBody(responseBody); + + server.enqueue(mockResponse); + + CompletableFuture response = client.sendRequestAsync(request); + RecordedRequest madeRequest = server.takeRequest(); + + assertThat(madeRequest.getPath(), is("/users/2")); + assertThat(madeRequest.getHeader("foo"), is("bar")); + assertThat(madeRequest.getMethod(), is("DELETE")); + + assertThat(response.get().getCode(), is(202)); + assertThat(response.get().isSuccessful(), is(true)); + assertThat(response.get().getBody(), is(responseBody)); + assertThat(response.get().getHeader("fiz"), is("bang")); + } + + @Test + public void handlesAPIError() throws Exception { + Auth0HttpRequest request = Auth0HttpRequest.newBuilder(server.url("/users/2").toString(), HttpMethod.GET) + .build(); + + DefaultHttpClient client = new DefaultHttpClient(new OkHttpClient()); + MockResponse mockResponse = new MockResponse() + .setResponseCode(404) + .setBody("User not found"); + + server.enqueue(mockResponse); + + Auth0HttpResponse response = client.sendRequest(request); + RecordedRequest madeRequest = server.takeRequest(); + + assertThat(madeRequest.getPath(), is("/users/2")); + assertThat(madeRequest.getMethod(), is("GET")); + + assertThat(response.getCode(), is(404)); + assertThat(response.isSuccessful(), is(false)); + assertThat(response.getBody(), is("User not found")); + } + + @Test + public void handlesAPIErrorAsync() throws Exception { + Auth0HttpRequest request = Auth0HttpRequest.newBuilder(server.url("/users/2").toString(), HttpMethod.GET) + .build(); + + DefaultHttpClient client = new DefaultHttpClient(new OkHttpClient()); + MockResponse mockResponse = new MockResponse() + .setResponseCode(404) + .setBody("User not found"); + + server.enqueue(mockResponse); + + CompletableFuture response = client.sendRequestAsync(request); + RecordedRequest madeRequest = server.takeRequest(); + + assertThat(madeRequest.getPath(), is("/users/2")); + assertThat(madeRequest.getMethod(), is("GET")); + + assertThat(response.get().getCode(), is(404)); + assertThat(response.get().isSuccessful(), is(false)); + assertThat(response.get().getBody(), is("User not found")); + } + + @Test + public void throwsIOException() { + Auth0HttpRequest request = Auth0HttpRequest.newBuilder(server.url("/users/2").toString(), HttpMethod.GET) + .build(); + + DefaultHttpClient client = new DefaultHttpClient(new OkHttpClient()); + // force IOException to be thrown by OkHttp when trying to parse response body + MockResponse mockResponse = new MockResponse() + .setResponseCode(200) + .setBody(new Buffer().write(new byte[2056])) + .setSocketPolicy(SocketPolicy.DISCONNECT_DURING_RESPONSE_BODY); + + server.enqueue(mockResponse); + + verifyThrows(IOException.class, () -> client.sendRequest(request)); + } + + @Test + public void throwsIOExceptionAsync() { + Auth0HttpRequest request = Auth0HttpRequest.newBuilder(server.url("/users/2").toString(), HttpMethod.GET) + .build(); + + DefaultHttpClient client = new DefaultHttpClient(new OkHttpClient()); + // force IOException to be thrown by OkHttp when trying to parse response body + MockResponse mockResponse = new MockResponse() + .setResponseCode(200) + .setBody(new Buffer().write(new byte[2056])) + .setSocketPolicy(SocketPolicy.DISCONNECT_DURING_RESPONSE_BODY); + + server.enqueue(mockResponse); + + CompletableFuture future = client.sendRequestAsync(request); + ExecutionException e = verifyThrows(ExecutionException.class, future::get); + assertThat(e.getCause(), is(instanceOf(IOException.class))); + } + + @Test + public void asyncHandlesNetworkError() { + OkHttpClient okClient = Mockito.mock(OkHttpClient.class); + okhttp3.Response response = Mockito.mock(okhttp3.Response.class); + Call call = Mockito.mock(Call.class); + + doReturn(call).when(okClient).newCall(any()); + + doAnswer(invocation -> { + ((Callback) invocation.getArgument(0)).onFailure(call, new IOException("Error!")); + return null; + }).when(call).enqueue(any()); + + DefaultHttpClient client = new DefaultHttpClient(okClient); + Auth0HttpRequest request = Auth0HttpRequest.newBuilder(server.url("/users/").toString(), HttpMethod.POST) + .withBody(HttpRequestBody.create("application/json", "{}".getBytes())) + .build(); + + CompletableFuture future = client.sendRequestAsync(request); + ExecutionException e = verifyThrows(ExecutionException.class, future::get); + assertThat(e.getCause(), is(instanceOf(IOException.class))); + } + + @Test + public void alwaysCloseResponseOnSuccessfulRequest() throws IOException { + okhttp3.Response response = Mockito.mock(okhttp3.Response.class); + + Call call = Mockito.mock(Call.class); + when(call.execute()).thenReturn(response); + + Headers headers = Mockito.mock(Headers.class); + when(response.headers()).thenReturn(headers); + + OkHttpClient client = Mockito.mock(OkHttpClient.class); + when(client.newCall(any())).thenReturn(call); + + Auth0HttpRequest request = Auth0HttpRequest.newBuilder(server.url("/users/").toString(), HttpMethod.POST) + .withBody(HttpRequestBody.create("application/json", "{}".getBytes())) + .build(); + + DefaultHttpClient auth0Client = new DefaultHttpClient(client); + auth0Client.sendRequest(request); + + verify(response, times(1)).close(); + } + + @Test + public void alwaysCloseResponseOnSuccessfulRequestAsync() throws Exception { + OkHttpClient okClient = Mockito.mock(OkHttpClient.class); + okhttp3.Response response = Mockito.mock(okhttp3.Response.class); + Call call = Mockito.mock(Call.class); + + doReturn(call).when(okClient).newCall(any()); + + doAnswer(invocation -> { + ((Callback) invocation.getArgument(0)).onResponse(call, response); + return null; + }).when(call).enqueue(any(Callback.class)); + + Headers headers = Mockito.mock(Headers.class); + when(response.headers()).thenReturn(headers); + + DefaultHttpClient client = new DefaultHttpClient(okClient); + Auth0HttpRequest request = Auth0HttpRequest.newBuilder(server.url("/users/").toString(), HttpMethod.POST) + .withBody(HttpRequestBody.create("application/json", "{}".getBytes())) + .build(); + + client.sendRequestAsync(request).get(); + verify(response, times(1)).close(); + } + + @Test + public void closesResponseOnAPIError() throws Exception { + okhttp3.Response response = Mockito.mock(okhttp3.Response.class); + + Call call = Mockito.mock(Call.class); + when(call.execute()).thenReturn(response); + + Headers headers = Mockito.mock(Headers.class); + when(response.headers()).thenReturn(headers); + + OkHttpClient okClient = Mockito.mock(OkHttpClient.class); + when(okClient.newCall(any())).thenReturn(call); + + Auth0HttpRequest request = Auth0HttpRequest.newBuilder(server.url("/users/").toString(), HttpMethod.POST) + .withBody(HttpRequestBody.create("application/json", "{}".getBytes())) + .build(); + + DefaultHttpClient client = new DefaultHttpClient(okClient); + MockResponse mockResponse = new MockResponse() + .setResponseCode(500) + .setBody("server error"); + + server.enqueue(mockResponse); + + Auth0HttpResponse aoResponse = client.sendRequest(request); + verify(response, times(1)).close(); + } + + @Test + public void closesResponseOnAPIErrorAsync() throws Exception { + OkHttpClient okClient = Mockito.mock(OkHttpClient.class); + okhttp3.Response response = Mockito.mock(okhttp3.Response.class); + Call call = Mockito.mock(Call.class); + + doReturn(call).when(okClient).newCall(any()); + + doAnswer(invocation -> { + ((Callback) invocation.getArgument(0)).onResponse(call, response); + return null; + }).when(call).enqueue(any(Callback.class)); + + Headers headers = Mockito.mock(Headers.class); + when(response.headers()).thenReturn(headers); + + DefaultHttpClient client = new DefaultHttpClient(okClient); + Auth0HttpRequest request = Auth0HttpRequest.newBuilder(server.url("/users/").toString(), HttpMethod.POST) + .withBody(HttpRequestBody.create("application/json", "{}".getBytes())) + .build(); + + MockResponse mockResponse = new MockResponse() + .setResponseCode(500) + .setBody("server error"); + + server.enqueue(mockResponse); + client.sendRequestAsync(request).get(); + verify(response, times(1)).close(); + } + + @Test + public void makesFormBodyPostRequest() throws Exception { + Map params = new HashMap<>(); + params.put("key", "value"); + params.put("key2", 5); + HttpRequestBody body = HttpRequestBody.create("application/x-www-form-urlencoded", new Auth0FormRequestBody(params)); + Auth0HttpRequest request = Auth0HttpRequest.newBuilder(server.url("/users/2").toString(), HttpMethod.POST) + .withHeaders(Collections.singletonMap("foo", "bar")) + .withBody(body) + .build(); + + DefaultHttpClient client = new DefaultHttpClient(new OkHttpClient()); + String responseBody = "{\"id\":\"123\", \"name\":\"timmy\"}"; + MockResponse mockResponse = new MockResponse() + .setResponseCode(200) + .setHeader("fiz", "bang") + .setBody(responseBody); + + server.enqueue(mockResponse); + + Auth0HttpResponse response = client.sendRequest(request); + RecordedRequest madeRequest = server.takeRequest(); + + assertThat(madeRequest.getPath(), is("/users/2")); + assertThat(madeRequest.getHeader("foo"), is("bar")); + assertThat(madeRequest.getMethod(), is("POST")); + + assertThat(response.getCode(), is(200)); + assertThat(response.isSuccessful(), is(true)); + assertThat(response.getBody(), is(responseBody)); + assertThat(response.getHeader("fiz"), is("bang")); + } + + ////////////////////////////////////////////////////////// + // HTTP CLIENT CONFIGURATION TESTS + ////////////////////////////////////////////////////////// + + @Test + public void shouldUseDefaultTimeoutIfNotSpecified() { + DefaultHttpClient client = DefaultHttpClient.newBuilder().build(); + assertThat(client.getOkClient().connectTimeoutMillis(), is(10 * 1000)); + assertThat(client.getOkClient().readTimeoutMillis(), is(10 * 1000)); + } + + @Test + public void shouldUseZeroIfNegativeTimeoutConfigured() { + DefaultHttpClient client = DefaultHttpClient.newBuilder() + .withConnectTimeout(-1) + .withReadTimeout(-1) + .build(); + + assertThat(client.getOkClient().connectTimeoutMillis(), is(0)); + assertThat(client.getOkClient().readTimeoutMillis(), is(0)); + + } + + @Test + public void shouldSetTimeoutsIfConfigured() { + DefaultHttpClient client = DefaultHttpClient.newBuilder() + .withConnectTimeout(20) + .withReadTimeout(30) + .build(); + + assertThat(client.getOkClient().connectTimeoutMillis(), is(20 * 1000)); + assertThat(client.getOkClient().readTimeoutMillis(), is(30 * 1000)); + } + + + @Test + public void shouldNotUseProxyByDefault() throws Exception { + DefaultHttpClient client = DefaultHttpClient.newBuilder().build(); + assertThat(client.getOkClient().proxy(), is(nullValue())); + Authenticator authenticator = client.getOkClient().proxyAuthenticator(); + assertThat(authenticator, is(notNullValue())); + + Route route = Mockito.mock(Route.class); + okhttp3.Request nonAuthenticatedRequest = new okhttp3.Request.Builder() + .url("https://test.com/app") + .addHeader("some-header", "some-value") + .build(); + okhttp3.Response nonAuthenticatedResponse = new okhttp3.Response.Builder() + .protocol(Protocol.HTTP_2) + .code(200) + .message("OK") + .request(nonAuthenticatedRequest) + .build(); + + okhttp3.Request processedRequest = authenticator.authenticate(route, nonAuthenticatedResponse); + assertThat(processedRequest, is(nullValue())); + } + + @Test + public void shouldUseProxy() throws Exception { + Proxy proxy = Mockito.mock(Proxy.class); + ProxyOptions proxyOptions = new ProxyOptions(proxy); + + DefaultHttpClient client = DefaultHttpClient.newBuilder() + .withProxy(proxyOptions) + .build(); + + assertThat(client.getOkClient().proxy(), is(proxy)); + Authenticator authenticator = client.getOkClient().proxyAuthenticator(); + assertThat(authenticator, is(notNullValue())); + + Route route = Mockito.mock(Route.class); + okhttp3.Request nonAuthenticatedRequest = new okhttp3.Request.Builder() + .url("https://test.com/app") + .addHeader("some-header", "some-value") + .build(); + okhttp3.Response nonAuthenticatedResponse = new okhttp3.Response.Builder() + .protocol(Protocol.HTTP_2) + .code(200) + .message("OK") + .request(nonAuthenticatedRequest) + .build(); + + okhttp3.Request processedRequest = authenticator.authenticate(route, nonAuthenticatedResponse); + + assertThat(processedRequest, is(nullValue())); + } + + @Test + public void shouldUseProxyWithAuthentication() throws Exception { + Proxy proxy = Mockito.mock(Proxy.class); + ProxyOptions proxyOptions = new ProxyOptions(proxy); + proxyOptions.setBasicAuthentication("johndoe", "psswd".toCharArray()); + assertThat(proxyOptions.getBasicAuthentication(), is("Basic am9obmRvZTpwc3N3ZA==")); + + DefaultHttpClient client = DefaultHttpClient.newBuilder() + .withProxy(proxyOptions) + .build(); + + assertThat(client.getOkClient().proxy(), is(proxy)); + Authenticator authenticator = client.getOkClient().proxyAuthenticator(); + assertThat(authenticator, is(notNullValue())); + + Route route = Mockito.mock(Route.class); + okhttp3.Request nonAuthenticatedRequest = new okhttp3.Request.Builder() + .url("https://test.com/app") + .addHeader("some-header", "some-value") + .build(); + okhttp3.Response nonAuthenticatedResponse = new okhttp3.Response.Builder() + .protocol(Protocol.HTTP_2) + .code(200) + .message("OK") + .request(nonAuthenticatedRequest) + .build(); + + okhttp3.Request processedRequest = authenticator.authenticate(route, nonAuthenticatedResponse); + + assertThat(processedRequest, is(notNullValue())); + assertThat(processedRequest.url(), is(HttpUrl.parse("https://test.com/app"))); + assertThat(processedRequest.header("Proxy-Authorization"), is(proxyOptions.getBasicAuthentication())); + assertThat(processedRequest.header("some-header"), is("some-value")); + } + + @Test + public void proxyShouldNotProcessAlreadyAuthenticatedRequest() throws Exception { + Proxy proxy = Mockito.mock(Proxy.class); + ProxyOptions proxyOptions = new ProxyOptions(proxy); + proxyOptions.setBasicAuthentication("johndoe", "psswd".toCharArray()); + assertThat(proxyOptions.getBasicAuthentication(), is("Basic am9obmRvZTpwc3N3ZA==")); + + DefaultHttpClient client = DefaultHttpClient.newBuilder() + .withProxy(proxyOptions) + .build(); + + assertThat(client.getOkClient().proxy(), is(proxy)); + Authenticator authenticator = client.getOkClient().proxyAuthenticator(); + assertThat(authenticator, is(notNullValue())); + + Route route = Mockito.mock(Route.class); + okhttp3.Request alreadyAuthenticatedRequest = new okhttp3.Request.Builder() + .url("https://test.com/app") + .addHeader("some-header", "some-value") + .header("Proxy-Authorization", "pre-existing-value") + .build(); + okhttp3.Response alreadyAuthenticatedResponse = new okhttp3.Response.Builder() + .protocol(Protocol.HTTP_2) + .code(200) + .message("OK") + .request(alreadyAuthenticatedRequest) + .build(); + + okhttp3.Request processedRequest = authenticator.authenticate(route, alreadyAuthenticatedResponse); + assertThat(processedRequest, is(nullValue())); + } + + @Test + public void shouldAddAndEnableTelemetryInterceptor() { + DefaultHttpClient client = DefaultHttpClient.newBuilder().build(); + assertThat(client.getOkClient().interceptors(), hasItem(isA(TelemetryInterceptor.class))); + + for (Interceptor i : client.getOkClient().interceptors()) { + if (i instanceof TelemetryInterceptor) { + TelemetryInterceptor telemetry = (TelemetryInterceptor) i; + assertThat(telemetry.isEnabled(), is(true)); + } + } + } + + @Test + public void shouldDisableTelemetryInterceptor() { + DefaultHttpClient client = DefaultHttpClient.newBuilder() + .telemetryEnabled(false) + .build(); + + assertThat(client.getOkClient().interceptors(), hasItem(isA(TelemetryInterceptor.class))); + + for (Interceptor i : client.getOkClient().interceptors()) { + if (i instanceof TelemetryInterceptor) { + TelemetryInterceptor telemetry = (TelemetryInterceptor) i; + assertThat(telemetry.isEnabled(), is(false)); + } + } + } + + @Test + public void shouldAddAndDisableLoggingInterceptor() { + DefaultHttpClient client = DefaultHttpClient.newBuilder().build(); + assertThat(client.getOkClient().interceptors(), hasItem(isA(HttpLoggingInterceptor.class))); + + for (Interceptor i : client.getOkClient().interceptors()) { + if (i instanceof HttpLoggingInterceptor) { + HttpLoggingInterceptor logging = (HttpLoggingInterceptor) i; + assertThat(logging.getLevel(), is(HttpLoggingInterceptor.Level.NONE)); + } + } + } + + @Test + public void shouldConfigureNoneLoggingFromOptions() { + LoggingOptions loggingOptions = new LoggingOptions(LoggingOptions.LogLevel.NONE); + DefaultHttpClient client = DefaultHttpClient.newBuilder() + .withLogging(loggingOptions) + .build(); + + assertThat(client.getOkClient().interceptors(), hasItem(isA(HttpLoggingInterceptor.class))); + + for (Interceptor i : client.getOkClient().interceptors()) { + if (i instanceof HttpLoggingInterceptor) { + HttpLoggingInterceptor logging = (HttpLoggingInterceptor) i; + assertThat(logging.getLevel(), is(HttpLoggingInterceptor.Level.NONE)); + } + } + } + + @Test + public void shouldConfigureBasicLoggingFromOptions() { + LoggingOptions loggingOptions = new LoggingOptions(LoggingOptions.LogLevel.BASIC); + DefaultHttpClient client = DefaultHttpClient.newBuilder() + .withLogging(loggingOptions) + .build(); + + assertThat(client.getOkClient().interceptors(), hasItem(isA(HttpLoggingInterceptor.class))); + + for (Interceptor i : client.getOkClient().interceptors()) { + if (i instanceof HttpLoggingInterceptor) { + HttpLoggingInterceptor logging = (HttpLoggingInterceptor) i; + assertThat(logging.getLevel(), is(HttpLoggingInterceptor.Level.BASIC)); + } + } + } + + @Test + public void shouldConfigureHeaderLoggingFromOptions() { + LoggingOptions loggingOptions = new LoggingOptions(LoggingOptions.LogLevel.HEADERS); + Set headersToRedact = new HashSet<>(); + headersToRedact.add("Authorization"); + headersToRedact.add("Cookie"); + loggingOptions.setHeadersToRedact(headersToRedact); + + DefaultHttpClient client = DefaultHttpClient.newBuilder() + .withLogging(loggingOptions) + .build(); + + assertThat(client.getOkClient().interceptors(), hasItem(isA(HttpLoggingInterceptor.class))); + + for (Interceptor i : client.getOkClient().interceptors()) { + if (i instanceof HttpLoggingInterceptor) { + HttpLoggingInterceptor logging = (HttpLoggingInterceptor) i; + assertThat(logging.getLevel(), is(HttpLoggingInterceptor.Level.HEADERS)); + } + } + } + + @Test + public void shouldConfigureBodyLoggingFromOptions() { + LoggingOptions loggingOptions = new LoggingOptions(LoggingOptions.LogLevel.BODY); + Set headersToRedact = new HashSet<>(); + headersToRedact.add("Authorization"); + headersToRedact.add("Cookie"); + loggingOptions.setHeadersToRedact(headersToRedact); + + DefaultHttpClient client = DefaultHttpClient.newBuilder() + .withLogging(loggingOptions) + .build(); + + assertThat(client.getOkClient().interceptors(), hasItem(isA(HttpLoggingInterceptor.class))); + + for (Interceptor i : client.getOkClient().interceptors()) { + if (i instanceof HttpLoggingInterceptor) { + HttpLoggingInterceptor logging = (HttpLoggingInterceptor) i; + assertThat(logging.getLevel(), is(HttpLoggingInterceptor.Level.BODY)); + } + } + } + + @Test + public void shouldUseDefaultMaxRetriesIfNotConfigured() { + DefaultHttpClient client = DefaultHttpClient.newBuilder() + .build(); + + assertThat(client.getOkClient().interceptors(), hasItem(isA(RateLimitInterceptor.class))); + + for (Interceptor i : client.getOkClient().interceptors()) { + if (i instanceof RateLimitInterceptor) { + RateLimitInterceptor rateLimitInterceptor = (RateLimitInterceptor) i; + assertThat(rateLimitInterceptor.getMaxRetries(), is(3)); + } + } + } + + @Test + public void shouldUseCustomMaxRetriesIfConfigured() { + DefaultHttpClient client = DefaultHttpClient.newBuilder() + .withMaxRetries(5) + .build(); + + assertThat(client.getOkClient().interceptors(), hasItem(isA(RateLimitInterceptor.class))); + + for (Interceptor i : client.getOkClient().interceptors()) { + if (i instanceof RateLimitInterceptor) { + RateLimitInterceptor rateLimitInterceptor = (RateLimitInterceptor) i; + assertThat(rateLimitInterceptor.getMaxRetries(), is(5)); + } + } + } + + @Test + public void shouldThrowOnNegativeMaxRetriesConfiguration() { + IllegalArgumentException iae = verifyThrows(IllegalArgumentException.class, + () -> DefaultHttpClient.newBuilder().withMaxRetries(-1).build(), + "Retries must be between zero and ten."); + } + + @Test + public void shouldThrowOnTooManyMaxRetriesConfiguration() { + IllegalArgumentException iae = verifyThrows(IllegalArgumentException.class, + () -> DefaultHttpClient.newBuilder().withMaxRetries(11).build(), + "Retries must be between zero and ten."); + } + + @Test + public void shouldUseDefaultMaxRequests() { + DefaultHttpClient client = DefaultHttpClient.newBuilder().build(); + assertThat(client.getOkClient().dispatcher().getMaxRequests(), is(64)); + } + + @Test + public void shouldUseConfiguredMaxRequests() { + DefaultHttpClient client = DefaultHttpClient.newBuilder() + .withMaxRequests(10) + .build(); + + assertThat(client.getOkClient().dispatcher().getMaxRequests(), is(10)); + } + + @Test + public void shouldThrowOnInValidMaxRequestsConfiguration() { + IllegalArgumentException iae = verifyThrows(IllegalArgumentException.class, + () -> DefaultHttpClient.newBuilder().withMaxRequests(0).build(), + "maxRequests must be one or greater."); + } + + @Test + public void shouldUseDefaultMaxRequestsPerHost() { + DefaultHttpClient client = DefaultHttpClient.newBuilder().build(); + assertThat(client.getOkClient().dispatcher().getMaxRequestsPerHost(), is(5)); + } + + @Test + public void shouldUseConfiguredMaxRequestsPerHost() { + DefaultHttpClient client = DefaultHttpClient.newBuilder() + .withMaxRequestsPerHost(10) + .build(); + assertThat(client.getOkClient().dispatcher().getMaxRequestsPerHost(), is(10)); + } + + @Test + public void shouldThrowOnInValidMaxRequestsPerHostConfiguration() { + IllegalArgumentException iae = verifyThrows(IllegalArgumentException.class, + () -> DefaultHttpClient.newBuilder().withMaxRequestsPerHost(0).build(), + "maxRequestsPerHost must be one or greater."); + } + +} diff --git a/src/test/java/com/auth0/net/multipart/FilePart.java b/src/test/java/com/auth0/net/client/multipart/FilePart.java similarity index 91% rename from src/test/java/com/auth0/net/multipart/FilePart.java rename to src/test/java/com/auth0/net/client/multipart/FilePart.java index d2c39997a..8e593ed7b 100644 --- a/src/test/java/com/auth0/net/multipart/FilePart.java +++ b/src/test/java/com/auth0/net/client/multipart/FilePart.java @@ -1,4 +1,4 @@ -package com.auth0.net.multipart; +package com.auth0.net.client.multipart; public class FilePart extends KeyValuePart { diff --git a/src/test/java/com/auth0/net/multipart/KeyValuePart.java b/src/test/java/com/auth0/net/client/multipart/KeyValuePart.java similarity index 88% rename from src/test/java/com/auth0/net/multipart/KeyValuePart.java rename to src/test/java/com/auth0/net/client/multipart/KeyValuePart.java index da8be292a..067576f97 100644 --- a/src/test/java/com/auth0/net/multipart/KeyValuePart.java +++ b/src/test/java/com/auth0/net/client/multipart/KeyValuePart.java @@ -1,4 +1,4 @@ -package com.auth0.net.multipart; +package com.auth0.net.client.multipart; public class KeyValuePart { diff --git a/src/test/java/com/auth0/net/multipart/RecordedMultipartRequest.java b/src/test/java/com/auth0/net/client/multipart/RecordedMultipartRequest.java similarity index 98% rename from src/test/java/com/auth0/net/multipart/RecordedMultipartRequest.java rename to src/test/java/com/auth0/net/client/multipart/RecordedMultipartRequest.java index 5d846828e..ce83605ad 100644 --- a/src/test/java/com/auth0/net/multipart/RecordedMultipartRequest.java +++ b/src/test/java/com/auth0/net/client/multipart/RecordedMultipartRequest.java @@ -1,4 +1,4 @@ -package com.auth0.net.multipart; +package com.auth0.net.client.multipart; import okhttp3.mockwebserver.RecordedRequest; import okio.Buffer; diff --git a/src/test/java/com/auth0/utils/AssertsTest.java b/src/test/java/com/auth0/utils/AssertsTest.java index 7121b33d2..f6a1e154c 100644 --- a/src/test/java/com/auth0/utils/AssertsTest.java +++ b/src/test/java/com/auth0/utils/AssertsTest.java @@ -1,17 +1,13 @@ package com.auth0.utils; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; +import org.junit.jupiter.api.Test; + +import static com.auth0.AssertsUtil.verifyThrows; public class AssertsTest { private static final String URI_NAME = "name"; - @SuppressWarnings("deprecation") - @Rule - public ExpectedException exception = ExpectedException.none(); - @Test public void succeedsForHttps() { Asserts.assertValidUrl("https://me.auth0.com", URI_NAME); @@ -56,22 +52,22 @@ public void succeedsWithCustomAppSchemeWithQueryParams() { @Test public void throwsIllegalArgumentExceptionWhenValueIsNull() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage(String.format("'%s' must be a valid URL!", URI_NAME)); - Asserts.assertValidUrl(null, URI_NAME); + verifyThrows(IllegalArgumentException.class, + () -> Asserts.assertValidUrl(null, URI_NAME), + String.format("'%s' must be a valid URL!", URI_NAME)); } @Test public void throwsIllegalArgumentExceptionWhenValueIsInvalid() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage(String.format("'%s' must be a valid URL!", URI_NAME)); - Asserts.assertValidUrl("not.a.domain", URI_NAME); + verifyThrows(IllegalArgumentException.class, + () -> Asserts.assertValidUrl("not.a.domain", URI_NAME), + String.format("'%s' must be a valid URL!", URI_NAME)); } @Test public void throwsIllegalArgumentExceptionWhenValueIsCustomSchemeAndInvalid() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage(String.format("'%s' must be a valid URL!", URI_NAME)); - Asserts.assertValidUrl("demo://host:%39%39/", URI_NAME); + verifyThrows(IllegalArgumentException.class, + () -> Asserts.assertValidUrl("demo://host:%39%39/", URI_NAME), + String.format("'%s' must be a valid URL!", URI_NAME)); } } diff --git a/src/test/java/com/auth0/utils/HttpResponseHeadersUtilsTest.java b/src/test/java/com/auth0/utils/HttpResponseHeadersUtilsTest.java new file mode 100644 index 000000000..77ddc8918 --- /dev/null +++ b/src/test/java/com/auth0/utils/HttpResponseHeadersUtilsTest.java @@ -0,0 +1,119 @@ +package com.auth0.utils; + +import com.auth0.net.TokenQuotaBucket; +import com.auth0.net.TokenQuotaLimit; +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertNull; + +public class HttpResponseHeadersUtilsTest { + + @Test + public void testGetClientQuotaLimitWithValidHeader() { + Map headers = new HashMap<>(); + headers.put("auth0-client-quota-limit", "per_hour;q=100;r=50;t=3600,per_day;q=1000;r=500;t=86400"); + + TokenQuotaBucket quotaBucket = HttpResponseHeadersUtils.getClientQuotaLimit(headers); + + assertNotNull(quotaBucket); + assertNotNull(quotaBucket.getPerHour()); + assertEquals(100, quotaBucket.getPerHour().getQuota()); + assertEquals(50, quotaBucket.getPerHour().getRemaining()); + assertEquals(3600, quotaBucket.getPerHour().getResetAfter()); + + assertNotNull(quotaBucket.getPerDay()); + assertEquals(1000, quotaBucket.getPerDay().getQuota()); + assertEquals(500, quotaBucket.getPerDay().getRemaining()); + assertEquals(86400, quotaBucket.getPerDay().getResetAfter()); + } + + @Test + public void testGetClientQuotaLimitWithMissingHeader() { + Map headers = new HashMap<>(); + + TokenQuotaBucket quotaBucket = HttpResponseHeadersUtils.getClientQuotaLimit(headers); + + assertNull(quotaBucket); + } + + @Test + public void testGetClientQuotaLimitWithOneBucketHeader() { + Map headers = new HashMap<>(); + headers.put("auth0-client-quota-limit", "per_hour;q=200;r=100;t=3600"); + + TokenQuotaBucket quotaBucket = HttpResponseHeadersUtils.getClientQuotaLimit(headers); + + assertNotNull(quotaBucket); + assertNotNull(quotaBucket.getPerHour()); + assertEquals(200, quotaBucket.getPerHour().getQuota()); + assertEquals(100, quotaBucket.getPerHour().getRemaining()); + assertEquals(3600, quotaBucket.getPerHour().getResetAfter()); + + assertNull(quotaBucket.getPerDay()); + } + + @Test + public void testGetOrganizationQuotaLimitWithValidHeader() { + Map headers = new HashMap<>(); + headers.put("auth0-organization-quota-limit", "per_hour;q=200;r=100;t=3600"); + + TokenQuotaBucket quotaBucket = HttpResponseHeadersUtils.getOrganizationQuotaLimit(headers); + + assertNotNull(quotaBucket); + assertNotNull(quotaBucket.getPerHour()); + assertEquals(200, quotaBucket.getPerHour().getQuota()); + assertEquals(100, quotaBucket.getPerHour().getRemaining()); + assertEquals(3600, quotaBucket.getPerHour().getResetAfter()); + + assertNull(quotaBucket.getPerDay()); + } + + @Test + public void testGetOrganizationQuotaLimitWithMissingHeader() { + Map headers = new HashMap<>(); + + TokenQuotaBucket quotaBucket = HttpResponseHeadersUtils.getOrganizationQuotaLimit(headers); + + assertNull(quotaBucket); + } + + @Test + public void testParseQuotaWithValidInput() { + String quotaHeader = "per_hour;q=300;r=150;t=3600,per_day;q=3000;r=1500;t=86400"; + + TokenQuotaBucket quotaBucket = HttpResponseHeadersUtils.parseQuota(quotaHeader); + + assertNotNull(quotaBucket); + assertNotNull(quotaBucket.getPerHour()); + assertEquals(300, quotaBucket.getPerHour().getQuota()); + assertEquals(150, quotaBucket.getPerHour().getRemaining()); + assertEquals(3600, quotaBucket.getPerHour().getResetAfter()); + + assertNotNull(quotaBucket.getPerDay()); + assertEquals(3000, quotaBucket.getPerDay().getQuota()); + assertEquals(1500, quotaBucket.getPerDay().getRemaining()); + assertEquals(86400, quotaBucket.getPerDay().getResetAfter()); + } + + @Test + public void testParseQuotaWithInvalidInput() { + String quotaHeader = "invalid_format"; + + TokenQuotaBucket quotaBucket = HttpResponseHeadersUtils.parseQuota(quotaHeader); + + assertNull(quotaBucket); + } + + @Test + public void testParseQuotaWithEmptyInput() { + String quotaHeader = ""; + + TokenQuotaBucket quotaBucket = HttpResponseHeadersUtils.parseQuota(quotaHeader); + + assertNull(quotaBucket); + } +} diff --git a/src/test/java/com/auth0/utils/tokens/IdTokenVerifierTest.java b/src/test/java/com/auth0/utils/tokens/IdTokenVerifierTest.java index 7df1c550d..1d4f69052 100644 --- a/src/test/java/com/auth0/utils/tokens/IdTokenVerifierTest.java +++ b/src/test/java/com/auth0/utils/tokens/IdTokenVerifierTest.java @@ -1,18 +1,19 @@ package com.auth0.utils.tokens; +import com.auth0.AssertsUtil; import com.auth0.exception.IdTokenValidationException; import com.auth0.jwt.JWT; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.interfaces.DecodedJWT; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import java.util.Calendar; import java.util.Date; -import static org.mockito.Mockito.*; +import static com.auth0.AssertsUtil.verifyThrows; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; public class IdTokenVerifierTest { @@ -23,146 +24,128 @@ public class IdTokenVerifierTest { private final static Date DEFAULT_CLOCK = new Date(1567400400000L); private final static Integer DEFAULT_CLOCK_SKEW = 60; - @SuppressWarnings("deprecation") - @Rule - public ExpectedException exception = ExpectedException.none(); - private SignatureVerifier signatureVerifier; - @Before + @BeforeEach public void setUp() { signatureVerifier = mock(SignatureVerifier.class); } @Test public void failsToCreateOptionsWhenIssuerIsNull() { - exception.expect(IllegalArgumentException.class); - IdTokenVerifier.init(null, "audience", signatureVerifier); + verifyThrows(IllegalArgumentException.class, + () -> IdTokenVerifier.init(null, "audience", signatureVerifier)); } @Test public void failsToCreateOptionsWhenAudienceIsNull() { - exception.expect(IllegalArgumentException.class); - IdTokenVerifier.init("issuer", null, signatureVerifier); + verifyThrows(IllegalArgumentException.class, + () -> IdTokenVerifier.init("issuer", null, signatureVerifier)); } @Test public void failsToCreateOptionsWhenVerifierIsNull() { - exception.expect(IllegalArgumentException.class); - IdTokenVerifier.init("issuer", "audience", null); + verifyThrows(IllegalArgumentException.class, + () -> IdTokenVerifier.init("issuer", "audience", null)); } @Test public void failsWhenIDTokenMissing() { - exception.expect(IdTokenValidationException.class); - exception.expectMessage("ID token is required but missing"); - - IdTokenVerifier.init("issuer", "audience", signatureVerifier) + AssertsUtil.verifyThrows(IdTokenValidationException.class, + () -> IdTokenVerifier.init("issuer", "audience", signatureVerifier) .build() - .verify(null); + .verify(null), + "ID token is required but missing"); } @Test public void failsWhenIDTokenEmpty() { - exception.expect(IdTokenValidationException.class); - exception.expectMessage("ID token is required but missing"); - - IdTokenVerifier.init("issuer", "audience", signatureVerifier) + AssertsUtil.verifyThrows(IdTokenValidationException.class, + () -> IdTokenVerifier.init("issuer", "audience", signatureVerifier) .build() - .verify(""); + .verify(""), + "ID token is required but missing"); } @Test public void failsWhenTokenCannotBeDecoded() { - exception.expect(IdTokenValidationException.class); - exception.expectMessage("ID token could not be decoded"); - - String token = "boom!"; - - SignatureVerifier signatureVerifier = SignatureVerifier.forHS256("secret"); - IdTokenVerifier.init(DOMAIN, AUDIENCE, signatureVerifier) + AssertsUtil.verifyThrows(IdTokenValidationException.class, + () -> IdTokenVerifier.init(DOMAIN, AUDIENCE, SignatureVerifier.forHS256("secret")) .build() - .verify(token); + .verify("boom"), + "ID token could not be decoded"); } @Test public void failsWhenSignatureIsInvalid() { - exception.expect(IdTokenValidationException.class); - exception.expectMessage("Invalid ID token signature"); - String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJub25jZSI6IjEyMzQiLCJpc3MiOiJodHRwczovL21lLmF1dGgwLmNvbS8iLCJhdWQiOiJkYU9nbkdzUlloa3d1NjIxdmYiLCJzdWIiOiJhdXRoMHx1c2VyMTIzIn0.a7ayNmFTxS2D-EIoUikoJ6dck7I8veWyxnje_mYD3qY"; - SignatureVerifier signatureVerifier = SignatureVerifier.forHS256("asdlk59ckvkr"); - IdTokenVerifier.init(DOMAIN, AUDIENCE, signatureVerifier) + AssertsUtil.verifyThrows(IdTokenValidationException.class, + () -> IdTokenVerifier.init(DOMAIN, AUDIENCE, SignatureVerifier.forHS256("asdlk59ckvkr")) .build() - .verify(token); + .verify(token), + "Invalid ID token signature"); } @Test public void failsWhenIssuerMissing() { - exception.expect(IdTokenValidationException.class); - exception.expectMessage("Issuer (iss) claim must be a string present in the ID token"); - String token = "eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJhdXRoMHwxMjM0NTY3ODkiLCJhdWQiOlsidG9rZW5zLXRlc3QtMTIzIiwiZXh0ZXJuYWwtdGVzdC0xMjMiXSwiZXhwIjoxNTY3NDg2ODAwLCJpYXQiOjE1NjczMTQwMDAsIm5vbmNlIjoiYTU5dms1OTIiLCJhenAiOiJ0b2tlbnMtdGVzdC0xMjMiLCJhdXRoX3RpbWUiOjE1NjczMTQwMDB9.B4PGlucyy-fJ4v5NNK2hntvjAf5m8dJf84WttwVnzV0ZlfPbYUSJm7Vc1ys7iMqXAQzAl2I8bDf2qhtLjaLpDKAH9JUvowUpCL7Bgjd7AEc1Te_IUwwxlpCupgseOEL2nrY8enP6On7BO7BBpngmVwnD1DvuA4lNoaaFyWUopha5Dxd5jw64wMqP4lz13C6Kqs8mINZkkw-NgE8DvWszaXeyPaowy-QpfXmPBnw75YLZlGcjr-WQsWQV7rUezq4Tl_11uPivR-fNcEWdG1mAtsnQnB_zJJKaHYlE0g4fey_6H9FKmCvcNkpBGo9ylbitb7jIuExbFEvEd2r_4wKl0g"; - configureVerifier(token) + AssertsUtil.verifyThrows(IdTokenValidationException.class, + () -> configureVerifier(token) .build() - .verify(token); + .verify(token), + "Issuer (iss) claim must be a string present in the ID token"); } @Test public void failsWhenIssuerInvalid() { - exception.expect(IdTokenValidationException.class); - exception.expectMessage(String.format("Issuer (iss) claim mismatch in the ID token, expected \"%s\", found \"%s\"", - "https://" + DOMAIN + "/", "something-else")); - String token = "eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJzb21ldGhpbmctZWxzZSIsInN1YiI6ImF1dGgwfDEyMzQ1Njc4OSIsImF1ZCI6WyJ0b2tlbnMtdGVzdC0xMjMiLCJleHRlcm5hbC10ZXN0LTEyMyJdLCJleHAiOjE1Njc0ODY4MDAsImlhdCI6MTU2NzMxNDAwMCwibm9uY2UiOiJhNTl2azU5MiIsImF6cCI6InRva2Vucy10ZXN0LTEyMyIsImF1dGhfdGltZSI6MTU2NzMxNDAwMH0.lHFHyg1ei3hK2vB7X1xB9nqksAEnxtv2KKpE_Gih6RezTruF9uZu1PAZTEwxhfj2UrQxwLqCb-t6wyVnxVpCsymSCq9JIiCVgg_cYV38siMs38N9y26BrVeyifj_VOP9Om_vI_hHjOzhi8WmysK2KKAQnn0skKAkq8epY4axCX3NkRaEIMhhTaITYia3GbJ5Qki8WDD9UVucUVOhgSZBV5p1dL39FKgc9k1MOVZJG-zAd_r5GsUIRk-xUwNX0WYwCR9sC2G-FjJTvlFph_4vksponoUWJ-LPTLM0RwGgmEUPhhnIG23UjsNwpnElY4gWfIL0hsO98-5DpGjn8Ejr0w"; - configureVerifier(token) + AssertsUtil.verifyThrows(IdTokenValidationException.class, + () -> configureVerifier(token) .build() - .verify(token); + .verify(token), + String.format("Issuer (iss) claim mismatch in the ID token, expected \"%s\", found \"%s\"", + "https://" + DOMAIN + "/", "something-else")); } @Test public void failsWhenSubMissing() { - exception.expect(IdTokenValidationException.class); - exception.expectMessage("Subject (sub) claim must be a string present in the ID token"); - String token = "eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJodHRwczovL3Rva2Vucy10ZXN0LmF1dGgwLmNvbS8iLCJhdWQiOlsidG9rZW5zLXRlc3QtMTIzIiwiZXh0ZXJuYWwtdGVzdC0xMjMiXSwiZXhwIjoxNTY3NDg2ODAwLCJpYXQiOjE1NjczMTQwMDAsIm5vbmNlIjoiYTU5dms1OTIiLCJhenAiOiJ0b2tlbnMtdGVzdC0xMjMiLCJhdXRoX3RpbWUiOjE1NjczMTQwMDB9.fDR9NSbbt75w9nzhL-eBfGjOp16HP2vfnO6m_Oav0xrmmgyYsBZSLOPd2C0O46bp6_2hKjeOUhnwYwjocsdXI4hvfQkyACERtneCkwHwSZPZK-1h6vgGF7b_7ILUywEcgo7F6e1qgFTM93Prqk63cCP53KgOBPyx02y0rqkhUOApCWRVBFrfP92tXvFN7E2phmpf9G68PPjwnEvvQtYOGjvFkaWSja7MKT98f7OxgbenBI_mAZy9LmOqUl3SKJOBe5Fibs1snI0l4nzrgQ1GNxVwyfHOdyq-srdGe8rlFx5kdhWh313EOzWxxGTg4RhGY7Tiz1QWago0VQ5yOt0w8A"; - configureVerifier(token) + AssertsUtil.verifyThrows(IdTokenValidationException.class, + () -> configureVerifier(token) .build() - .verify(token); + .verify(token), + "Subject (sub) claim must be a string present in the ID token"); } @Test public void failsWhenAudienceMissing() { - exception.expect(IdTokenValidationException.class); - exception.expectMessage("Audience (aud) claim must be a string or array of strings present in the ID token"); - String token = "eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJodHRwczovL3Rva2Vucy10ZXN0LmF1dGgwLmNvbS8iLCJzdWIiOiJhdXRoMHwxMjM0NTY3ODkiLCJleHAiOjE1Njc0ODY4MDAsImlhdCI6MTU2NzMxNDAwMCwibm9uY2UiOiJhNTl2azU5MiIsImF6cCI6InRva2Vucy10ZXN0LTEyMyIsImF1dGhfdGltZSI6MTU2NzMxNDAwMH0.XM-IM9CIZ2cJpZZaKooMSmNgvwHPTse6kcIOPATgewRZxrDdCEjtPHmzmSuyDGy84vSR__DJS_kM2jWWwbkjB_PahXes210dpUqitRW3is9xV0-k0LkVwxmhHCM-e9sClbTbcs4zLv6WWFRq4UEU5DU6HhuHLQeeH0eO2Nv_tkvu-JdpmoepHPjW3ecMs0lhzXRT6_2o-ErTPdYt4W6yqpBG57HRIMzs9F72AWcPC6vhLY0IhMqXaq68Ma3jnEPIXUmv52bll0PuQVBqKd-eDH_jD0ZHFUCkwbfWPrkhJz5Q5qLzSzUjnrWKA3KgP4_Z1KfHY2-nQA2ynMgNFSn_eA"; - configureVerifier(token) + AssertsUtil.verifyThrows(IdTokenValidationException.class, + () -> configureVerifier(token) .build() - .verify(token); + .verify(token), + "Audience (aud) claim must be a string or array of strings present in the ID token"); } @Test public void failsWhenAudienceDoesNotContainClientId() { - exception.expect(IdTokenValidationException.class); - exception.expectMessage(String.format("Audience (aud) claim mismatch in the ID token; expected \"%s\" but found \"%s\"", AUDIENCE, "[external-test-123]")); - String token = "eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJodHRwczovL3Rva2Vucy10ZXN0LmF1dGgwLmNvbS8iLCJzdWIiOiJhdXRoMHwxMjM0NTY3ODkiLCJhdWQiOiJleHRlcm5hbC10ZXN0LTEyMyIsImV4cCI6MTU2NzQ4NjgwMCwiaWF0IjoxNTY3MzE0MDAwLCJub25jZSI6ImE1OXZrNTkyIiwiYXpwIjoidG9rZW5zLXRlc3QtMTIzIiwiYXV0aF90aW1lIjoxNTY3MzE0MDAwfQ.SxeNIhm8reywgtSSkZ6jCpbZ8KyC09couFjpcrJFktAYKmJZnGQkv0gQLNUuGejORvysznOlhfO2nkF10yT6pKBiye9xZ8TstWQBorDKHL-74n6ZAxjPg1F0vHNokZq0zpPkwV-gKIFY6aPw3vyZTxzR6CMyoJdwc19A0RXPzPt6T7csQeqX0lzGEqqeIbU4VI5XM5RG1VvN82CgTlOQXlFZrKhyJx_xwslyWWDzx7tpPNid1wusvfznTGxoWO2wUBCyW6EhmyHp2euFi1gdJqHQVbrydutPtQ-FGQEwyWACNN8kBWqQ7UEbqimg6C0NTGrRkkKkJ79DmiW7aULHZQ"; - configureVerifier(token) + AssertsUtil.verifyThrows(IdTokenValidationException.class, + () -> configureVerifier(token) .build() - .verify(token); + .verify(token), + String.format("Audience (aud) claim mismatch in the ID token; expected \"%s\" but found \"%s\"", AUDIENCE, "[external-test-123]")); } @Test public void failsWhenExpClaimMissing() { - exception.expect(IdTokenValidationException.class); - exception.expectMessage("Expiration Time (exp) claim must be a number present in the ID token"); - String token = "eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJodHRwczovL3Rva2Vucy10ZXN0LmF1dGgwLmNvbS8iLCJzdWIiOiJhdXRoMHwxMjM0NTY3ODkiLCJhdWQiOlsidG9rZW5zLXRlc3QtMTIzIiwiZXh0ZXJuYWwtdGVzdC0xMjMiXSwiaWF0IjoxNTY3MzE0MDAwLCJub25jZSI6ImE1OXZrNTkyIiwiYXpwIjoidG9rZW5zLXRlc3QtMTIzIiwiYXV0aF90aW1lIjoxNTY3MzE0MDAwfQ.b6saYAZCnCSzpVO0nrAUKVSC1n3GoqUfwrjOXG5gVxda0oFohpYJe68QwzsTmS4fOm7JtbN1FqjVRN6S4i-BnH-XGnciGOMFF4EfaOzsgo7DCrrLrjfx6rmqW8UPYalbfJTQL8mXYnLOxzMGP3DEXNlk-41GSZoFujwTAIqYjrV_Y3MUGYmzcVxdL_h2psLm_p07knMLCm7Cuo8znzKrU4PtuaLflvzorg57S4BD79oLv4uv0_dmhwPUgJDvqWeicR5Qry4aX2L5BT6V-nBWAcu3qVZDymSKcjtTebxszxY1siyA7BQe88ZmgP1bW1KXtMk_fOGsgWHFdu_AH77yow"; - configureVerifier(token) + AssertsUtil.verifyThrows(IdTokenValidationException.class, + () -> configureVerifier(token) .build() - .verify(token); + .verify(token), + "Expiration Time (exp) claim must be a number present in the ID token"); } @Test @@ -173,15 +156,14 @@ public void failsWhenExpClaimInvalidOutsideDefaultLeeway() { Date clock = new Date(1567314000000L); clock.setTime(clock.getTime() + ((DEFAULT_CLOCK_SKEW + 1) * 1000)); - exception.expect(IdTokenValidationException.class); - exception.expectMessage(String.format("Expiration Time (exp) claim error in the ID token; current time (%d) is after expiration time (%d)", - clock.getTime() / 1000, actualExpTime + DEFAULT_CLOCK_SKEW)); - String token = "eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJodHRwczovL3Rva2Vucy10ZXN0LmF1dGgwLmNvbS8iLCJzdWIiOiJhdXRoMHwxMjM0NTY3ODkiLCJhdWQiOlsidG9rZW5zLXRlc3QtMTIzIiwiZXh0ZXJuYWwtdGVzdC0xMjMiXSwiZXhwIjoxNTY3MzE0MDAwLCJpYXQiOjE1NjczMTQwMDAsIm5vbmNlIjoiYTU5dms1OTIiLCJhenAiOiJ0b2tlbnMtdGVzdC0xMjMiLCJhdXRoX3RpbWUiOjE1NjczMTQwMDB9.uDn-4wtiigGddUw2kis_QyfDE3w75rWvu9NolMgD3b7l4_fedhQOk-z_mYID588ZXpnpLRKKiD5I2IFsXl7Qcc10rx1LIZxNqdzyc3VrgFf677x7fFZ4guR2WalH-zdJEluruMRdCIFQczIjXnGKPHGQ8gPH1LRozv43dl-bO2viX6MU4pTgNq3GIsU4ureyHrx1o9JSqF4b_RzuYvVWVVX7ABC2csMJP_ocVbEIQjUBhp1V7VcQY-Zgq0prk_HvY13g8FxK4KvSza637ZWAfonn599SKuy22PeMJqDfd64SbunWrt-mKBz9PHeAo9t4LJPLsAqSd3IQ2aJTsnqJRA"; - configureVerifier(token) - .withClock(clock) - .build() - .verify(token); + AssertsUtil.verifyThrows(IdTokenValidationException.class, + () -> configureVerifier(token) + .withClock(clock) + .build() + .verify(token), + String.format("Expiration Time (exp) claim error in the ID token; current time (%d) is after expiration time (%d)", + clock.getTime() / 1000, actualExpTime + DEFAULT_CLOCK_SKEW)); } @Test @@ -209,15 +191,14 @@ public void failsWhenExpClaimInvalidOutsideCustomLeeway() { Date clock = new Date(1567314000000L); clock.setTime(clock.getTime() + ((leeway + 1) * 1000)); - exception.expect(IdTokenValidationException.class); - exception.expectMessage(String.format("Expiration Time (exp) claim error in the ID token; current time (%d) is after expiration time (%d)", + AssertsUtil.verifyThrows(IdTokenValidationException.class, + () -> configureVerifier(token) + .withClock(clock) + .withLeeway(leeway) + .build() + .verify(token), + String.format("Expiration Time (exp) claim error in the ID token; current time (%d) is after expiration time (%d)", clock.getTime() / 1000, ((actualExp.getTime() / 1000) + leeway))); - - configureVerifier(token) - .withClock(clock) - .withLeeway(leeway) - .build() - .verify(token); } @Test @@ -238,25 +219,22 @@ public void succeedsWhenExpClaimInPastButWithinCustomLeeway() { @Test public void failsWhenIatClaimMissing() { - exception.expect(IdTokenValidationException.class); - exception.expectMessage("Issued At (iat) claim must be a number present in the ID token"); - String token = "eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJodHRwczovL3Rva2Vucy10ZXN0LmF1dGgwLmNvbS8iLCJzdWIiOiJhdXRoMHwxMjM0NTY3ODkiLCJhdWQiOlsidG9rZW5zLXRlc3QtMTIzIiwiZXh0ZXJuYWwtdGVzdC0xMjMiXSwiZXhwIjoxNTY3NDg2ODAwLCJub25jZSI6ImE1OXZrNTkyIiwiYXpwIjoidG9rZW5zLXRlc3QtMTIzIiwiYXV0aF90aW1lIjoxNTY3MzE0MDAwfQ.SJDgK8W9Y8stMtE9LG2OzHzXzbIDCXg8lRhKyOim4rRXbkg3k0on7gCzN-sy2d5z5TQ-lQzbY3V4z-so3ltVDUYd_8RjmUiKgNK_95UsxfTDM2BlBEQ6USMVl3ojC5jcTBhg5MF16ZBEn94IjIGC9Uks9GPseM-JrtUPx4Uj5VvsBtmeKxLc3rSGt7rYC4JU65Oa-O5pFYRSCbNzRFNHRlmnb5b2uPHxoVLjrJAT0FhlXcsNgfz65MlbXBgAyz7xjCEhw_tTpvptaCwPTeG0mgBYlGQ7Sl3xHJzgG4jLbA7Pvvfcx0MpBPHUZxADh1FFQnf2nHB0ppddiDfOq2mHNA"; - - configureVerifier(token) - .build() - .verify(token); + AssertsUtil.verifyThrows(IdTokenValidationException.class, + () -> configureVerifier(token) + .build() + .verify(token), + "Issued At (iat) claim must be a number present in the ID token"); } @Test public void failsWhenNonceConfiguredButNoNonceClaimSent() { - exception.expect(IdTokenValidationException.class); - exception.expectMessage("Nonce (nonce) claim must be a string present in the ID token"); - String token = "eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJodHRwczovL3Rva2Vucy10ZXN0LmF1dGgwLmNvbS8iLCJzdWIiOiJhdXRoMHwxMjM0NTY3ODkiLCJhdWQiOlsidG9rZW5zLXRlc3QtMTIzIiwiZXh0ZXJuYWwtdGVzdC0xMjMiXSwiZXhwIjoxNTY3NDg2ODAwLCJpYXQiOjE1NjczMTQwMDAsImF6cCI6InRva2Vucy10ZXN0LTEyMyIsImF1dGhfdGltZSI6MTU2NzMxNDAwMH0.ZRYK4s72pKXJUSadByPp_MNyuaACmPCyj9RaIfxuTTLXE45YJ0toLK6XjjDv_861E_fRmEKMthnJAmHcKXiDWGb73l3iDtD7clockBOo3KJO2cwkM1uYNpG1kbNkg6WDvgGlVsC7buxr8dbL8fI2e0g53Jl48lE9Ohi5Z_7iRmRoVAx5HE60UDfEqFeAKZyu5VsAahp9q3PwhLfaJVDobtAzWP0LcRA3x8FOA0ZdBBNpvRmeBRugU2GQTSDLSMtGzgi5xXUwXly7pr5bX-lIYICU1Q9R5n-8uYlEaFuiaYTqzxY0fmSzzGeFkwrj7b0yTQ2OwAFVT3MWCSbvjKsy-JWQ"; - configureVerifier(token) + AssertsUtil.verifyThrows(IdTokenValidationException.class, + () -> configureVerifier(token) .build() - .verify(token, "nonce"); + .verify(token, "nonce"), + "Nonce (nonce) claim must be a string present in the ID token"); } @Test @@ -266,23 +244,21 @@ public void failsWhenNonceIsInvalid() { String expectedNonce = "nonce"; String actualNonce = "000999"; - exception.expect(IdTokenValidationException.class); - exception.expectMessage(String.format("Nonce (nonce) claim mismatch in the ID token; expected \"%s\", found \"%s\"", expectedNonce, actualNonce)); - - configureVerifier(token) + AssertsUtil.verifyThrows(IdTokenValidationException.class, + () -> configureVerifier(token) .build() - .verify(token, expectedNonce); + .verify(token, expectedNonce), + String.format("Nonce (nonce) claim mismatch in the ID token; expected \"%s\", found \"%s\"", expectedNonce, actualNonce)); } @Test public void failsWhenAudClaimHasMultipleItemsButAzpMissing() { - exception.expect(IdTokenValidationException.class); - exception.expectMessage("Authorized Party (azp) claim must be a string present in the ID token when Audience (aud) claim has multiple values"); - String token = "eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJodHRwczovL3Rva2Vucy10ZXN0LmF1dGgwLmNvbS8iLCJzdWIiOiJhdXRoMHwxMjM0NTY3ODkiLCJhdWQiOlsidG9rZW5zLXRlc3QtMTIzIiwiZXh0ZXJuYWwtdGVzdC0xMjMiXSwiZXhwIjoxNTY3NDg2ODAwLCJpYXQiOjE1NjczMTQwMDAsIm5vbmNlIjoiYTU5dms1OTIiLCJhenAiOjQyLCJhdXRoX3RpbWUiOjE1NjczMTQwMDB9.SliF71jOX9JsGeUPCySf3ucY_tGr3uh183cbcUN9ze3qRiOAc5bi7vdsBtODtlVJgsx0Elt0JrISTJ8SoNkpA4SxrjFpxSsfzPBwQtJrlg7pqflgBH7g6zKGVGRs2Z0jxZaCvXQvRuUZRZwFIncZ2zTFIDI3X5xLeJAGRGWaInOvLLlumGzWzfNLUG_G5uHZQW6sRgyIw9qrdqEWXO6sGjOBG9Au6jIo2IH0I53-UujAnNHWeJRPsM5xw2bHPteIde1xn4N0w26BlZ4GEQifVQDFw3ukah35SQ-ENMMS58Siu-sysF5F3oxdwVaMidyYgrD2VUN_iXIaMPwA2i0M5Q"; - configureVerifier(token) + AssertsUtil.verifyThrows(IdTokenValidationException.class, + () -> configureVerifier(token) .build() - .verify(token); + .verify(token), + "Authorized Party (azp) claim must be a string present in the ID token when Audience (aud) claim has multiple values"); } @Test @@ -290,23 +266,21 @@ public void failsWhenAudClaimHasMultipleItemsButAzpInvalid() { String token = "eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJodHRwczovL3Rva2Vucy10ZXN0LmF1dGgwLmNvbS8iLCJzdWIiOiJhdXRoMHwxMjM0NTY3ODkiLCJhdWQiOlsidG9rZW5zLXRlc3QtMTIzIiwiZXh0ZXJuYWwtdGVzdC0xMjMiXSwiZXhwIjoxNTY3NDg2ODAwLCJpYXQiOjE1NjczMTQwMDAsIm5vbmNlIjoiYTU5dms1OTIiLCJhenAiOiJleHRlcm5hbC10ZXN0LTEyMyIsImF1dGhfdGltZSI6MTU2NzMxNDAwMH0.GLuChuSum2S6h79rfRbJrJfe_7Fw_D6RHXj9zrAhixoNLMyBosO2GBPsOgoaLTDMonJzCyqskjan-w-SJ5nw7fUmDkWfPVjXcS0x5pt72j0dgfLMu6eOFIA9jWHWN4hsN3XKJktZ9202AohI8fXO5BYQ-jMi0HWQaiUj3f6wITHEN6fTydLo_t24hriExkO1670AgzM22BVTfb-JJlrs32t6ffY77zrF5ahIg_h4ROgrcf_3LejF7ZnubHbpJ-wX-byxW9YXT5tN_JjD5EP6jC37s9iL8ArGEZtBzHVfCO0kqlaH-9PVZXgz8SjMSJ8iA2fXXN0L35ySdzida3hhzw"; String actualAzp = "external-test-123"; - exception.expect(IdTokenValidationException.class); - exception.expectMessage(String.format("Authorized Party (azp) claim mismatch in the ID token; expected \"%s\", found \"%s\"", AUDIENCE, actualAzp)); - - configureVerifier(token) + AssertsUtil.verifyThrows(IdTokenValidationException.class, + () -> configureVerifier(token) .build() - .verify(token); + .verify(token), + String.format("Authorized Party (azp) claim mismatch in the ID token; expected \"%s\", found \"%s\"", AUDIENCE, actualAzp)); } @Test public void failsWhenMaxAgeSentButAuthTimeClaimMissing() { - exception.expect(IdTokenValidationException.class); - exception.expectMessage("Authentication Time (auth_time) claim must be a number present in the ID token when Max Age (max_age) is specified"); - String token = "eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJodHRwczovL3Rva2Vucy10ZXN0LmF1dGgwLmNvbS8iLCJzdWIiOiJhdXRoMHwxMjM0NTY3ODkiLCJhdWQiOlsidG9rZW5zLXRlc3QtMTIzIiwiZXh0ZXJuYWwtdGVzdC0xMjMiXSwiZXhwIjoxNTY3NDg2ODAwLCJpYXQiOjE1NjczMTQwMDAsIm5vbmNlIjoiYTU5dms1OTIiLCJhenAiOiJ0b2tlbnMtdGVzdC0xMjMifQ.Gb36qNHgQgac1fXh9AHX7ZMroymT0j4TjNol3ZirbIOyxuHV4OxCbGcoAAxC8Zt_dIc3DH9SX3QUIwTkE3DsFxS-VJ58R2d9RbXJl5p8pO1sJNFjo59njLKbiBxVil4z8PUsw77c_4f2QtKn6LHzhGqL9CS84LUCgNPPBsBHYyNRJDwIauPrrLyOsZAS3dWlZiUDBFurSYe0Y-O6d8zF_uKOcTD8A2E3SQQlZJQ12T94IprQ9V0tbbWI8VSGQ23JghR62QwZC-rBOF9pQMcLLCNRLFTTF9sXqZuS9XRv7PZ6rRjaonHDWn8WqGjSleWSycPsvwvjjSUVR8Z3iDBZig"; - configureVerifier(token) - .build() - .verify(token, null,200); + AssertsUtil.verifyThrows(IdTokenValidationException.class, + () -> configureVerifier(token) + .build() + .verify(token, null, 200), + "Authentication Time (auth_time) claim must be a number present in the ID token when Max Age (max_age) is specified"); } @Test @@ -320,14 +294,13 @@ public void failsWhenMaxSentButAuthTimeInvalidWithinLeeway() { Date clock = new Date(1567314000000L); clock.setTime(clock.getTime() + ((maxAge + (DEFAULT_CLOCK_SKEW + 1)) * 1000)); - exception.expect(IdTokenValidationException.class); - exception.expectMessage(String.format("Authentication Time (auth_time) claim in the ID token indicates that too much time has passed since the last end-user authentication. Current time (%d) is after last auth at (%d)", + AssertsUtil.verifyThrows(IdTokenValidationException.class, + () -> configureVerifier(token) + .withClock(clock) + .build() + .verify(token, null, maxAge), + String.format("Authentication Time (auth_time) claim in the ID token indicates that too much time has passed since the last end-user authentication. Current time (%d) is after last auth at (%d)", clock.getTime() / 1000, actualAuthTime + maxAge + DEFAULT_CLOCK_SKEW)); - - configureVerifier(token) - .withClock(clock) - .build() - .verify(token, null, maxAge); } @Test @@ -358,15 +331,14 @@ public void failsWhenMaxSentButAuthTimeInvalidWithCustomLeeway() { Date clock = new Date(1567314000000L); clock.setTime(clock.getTime() + ((maxAge + customLeeway + 1) * 1000)); - exception.expect(IdTokenValidationException.class); - exception.expectMessage(String.format("Authentication Time (auth_time) claim in the ID token indicates that too much time has passed since the last end-user authentication. Current time (%d) is after last auth at (%d)", + AssertsUtil.verifyThrows(IdTokenValidationException.class, + () -> configureVerifier(token) + .withClock(clock) + .withLeeway(customLeeway) + .build() + .verify(token, null, maxAge), + String.format("Authentication Time (auth_time) claim in the ID token indicates that too much time has passed since the last end-user authentication. Current time (%d) is after last auth at (%d)", clock.getTime() / 1000, actualAuthTime + maxAge + customLeeway)); - - configureVerifier(token) - .withClock(clock) - .withLeeway(customLeeway) - .build() - .verify(token, null, maxAge); } @Test @@ -448,57 +420,94 @@ public void succeedsWithValidTokenUsingDefaultClockAndHttpsDomain() { } @Test - public void succeedsWhenOrganizationMatchesExpected() { + public void succeedsWhenOrganizationNamdMatchesExpected() { String token = JWT.create() .withSubject("auth0|sdk458fks") .withAudience(AUDIENCE) .withIssuedAt(getYesterday()) .withExpiresAt(getTomorrow()) .withIssuer("https://" + DOMAIN + "/") - .withClaim("org_id", "org_123") + .withClaim("org_name", "my org") .sign(Algorithm.HMAC256("secret")); String jwt = JWT.decode(token).getToken(); configureVerifier(jwt) - .withOrganization("org_123") + .withOrganization("my org") .build() .verify(jwt); } @Test - public void failsWhenOrganizationDoesNotMatchExpected() { - exception.expect(IdTokenValidationException.class); - exception.expectMessage("Organization (org_id) claim mismatch in the ID token; expected \"org_abc\" but found \"org_123\""); + public void failsWhenOrganizationNameDoesNotMatchExpected() { + String token = JWT.create() + .withSubject("auth0|sdk458fks") + .withAudience(AUDIENCE) + .withIssuedAt(getYesterday()) + .withExpiresAt(getTomorrow()) + .withIssuer("https://" + DOMAIN + "/") + .withClaim("org_name", "my org") + .sign(Algorithm.HMAC256("secret")); + String jwt = JWT.decode(token).getToken(); + + AssertsUtil.verifyThrows(IdTokenValidationException.class, + () -> configureVerifier(jwt) + .withOrganization("your org") + .build() + .verify(jwt), + "Organization (org_name) claim mismatch in the ID token; expected \"your org\" but found \"my org\""); + } + + @Test + public void failsWhenOrganizationNameExpectedButClaimIsNotString() { String token = JWT.create() .withSubject("auth0|sdk458fks") .withAudience(AUDIENCE) .withIssuedAt(getYesterday()) .withExpiresAt(getTomorrow()) .withIssuer("https://" + DOMAIN + "/") - .withClaim("org_id", "org_123") + .withClaim("org_name", 42) + .sign(Algorithm.HMAC256("secret")); + + String jwt = JWT.decode(token).getToken(); + + AssertsUtil.verifyThrows(IdTokenValidationException.class, () -> { + configureVerifier(jwt) + .withOrganization("my org") + .build() + .verify(jwt); + }, + "Organization name (org_name) claim must be a string present in the ID token"); + } + + @Test + public void succeedsWhenOrganizationNameNotSpecifiedButIsPresent() { + String token = JWT.create() + .withSubject("auth0|sdk458fks") + .withAudience(AUDIENCE) + .withIssuedAt(getYesterday()) + .withExpiresAt(getTomorrow()) + .withIssuer("https://" + DOMAIN + "/") + .withClaim("org_name", "my org") .sign(Algorithm.HMAC256("secret")); String jwt = JWT.decode(token).getToken(); configureVerifier(jwt) - .withOrganization("org_abc") .build() .verify(jwt); } @Test - public void failsWhenOrganizationExpectedButNotPresent() { - exception.expect(IdTokenValidationException.class); - exception.expectMessage("Organization Id (org_id) claim must be a string present in the ID token"); - + public void succeedsWhenOrganizationIdMatchesExpected() { String token = JWT.create() .withSubject("auth0|sdk458fks") .withAudience(AUDIENCE) .withIssuedAt(getYesterday()) .withExpiresAt(getTomorrow()) .withIssuer("https://" + DOMAIN + "/") + .withClaim("org_id", "org_123") .sign(Algorithm.HMAC256("secret")); String jwt = JWT.decode(token).getToken(); @@ -510,29 +519,110 @@ public void failsWhenOrganizationExpectedButNotPresent() { } @Test - public void failsWhenOrganizationExpectedButClaimIsNotString() { - exception.expect(IdTokenValidationException.class); - exception.expectMessage("Organization Id (org_id) claim must be a string present in the ID token"); + public void failsWhenOrganizationIdDoesNotMatchExpected() { + String token = JWT.create() + .withSubject("auth0|sdk458fks") + .withAudience(AUDIENCE) + .withIssuedAt(getYesterday()) + .withExpiresAt(getTomorrow()) + .withIssuer("https://" + DOMAIN + "/") + .withClaim("org_id", "org_123") + .sign(Algorithm.HMAC256("secret")); + + String jwt = JWT.decode(token).getToken(); + AssertsUtil.verifyThrows(IdTokenValidationException.class, + () -> configureVerifier(jwt) + .withOrganization("org_abc") + .build() + .verify(jwt), + "Organization (org_id) claim mismatch in the ID token; expected \"org_abc\" but found \"org_123\""); + } + + @Test + public void failsWhenOrganizationIdDoesNotMatchExpected_caseSensitive() { String token = JWT.create() .withSubject("auth0|sdk458fks") .withAudience(AUDIENCE) .withIssuedAt(getYesterday()) .withExpiresAt(getTomorrow()) .withIssuer("https://" + DOMAIN + "/") - .withClaim("org_id", 42) + .withClaim("org_id", "oRg_123") + .sign(Algorithm.HMAC256("secret")); + + String jwt = JWT.decode(token).getToken(); + + AssertsUtil.verifyThrows(IdTokenValidationException.class, + () -> configureVerifier(jwt) + .withOrganization("org_123") + .build() + .verify(jwt), + "Organization (org_id) claim mismatch in the ID token; expected \"org_123\" but found \"oRg_123\""); + } + + @Test + public void failsWhenOrganizationIdExpectedButNotPresent() { + String token = JWT.create() + .withSubject("auth0|sdk458fks") + .withAudience(AUDIENCE) + .withIssuedAt(getYesterday()) + .withExpiresAt(getTomorrow()) + .withIssuer("https://" + DOMAIN + "/") + .sign(Algorithm.HMAC256("secret")); + + String jwt = JWT.decode(token).getToken(); + + AssertsUtil.verifyThrows(IdTokenValidationException.class, + () -> configureVerifier(jwt) + .withOrganization("org_123") + .build() + .verify(jwt), + "Organization Id (org_id) claim must be a string present in the ID token"); + } + + @Test + public void succeedsWhenOrganizationNameDoesNotMatchExpected_caseInsensitive() { + String token = JWT.create() + .withSubject("auth0|sdk458fks") + .withAudience(AUDIENCE) + .withIssuedAt(getYesterday()) + .withExpiresAt(getTomorrow()) + .withIssuer("https://" + DOMAIN + "/") + .withClaim("org_name", "my org") .sign(Algorithm.HMAC256("secret")); String jwt = JWT.decode(token).getToken(); configureVerifier(jwt) - .withOrganization("org_123") + .withOrganization("My org") .build() .verify(jwt); } @Test - public void succeedsWhenOrganizationNotSpecifiedButIsPresent() { + public void failsWhenOrganizationIdExpectedButClaimIsNotString() { + String token = JWT.create() + .withSubject("auth0|sdk458fks") + .withAudience(AUDIENCE) + .withIssuedAt(getYesterday()) + .withExpiresAt(getTomorrow()) + .withIssuer("https://" + DOMAIN + "/") + .withClaim("org_id", 42) + .sign(Algorithm.HMAC256("secret")); + + String jwt = JWT.decode(token).getToken(); + + AssertsUtil.verifyThrows(IdTokenValidationException.class, () -> { + configureVerifier(jwt) + .withOrganization("org_123") + .build() + .verify(jwt); + }, + "Organization Id (org_id) claim must be a string present in the ID token"); + } + + @Test + public void succeedsWhenOrganizationIdNotSpecifiedButIsPresent() { String token = JWT.create() .withSubject("auth0|sdk458fks") .withAudience(AUDIENCE) diff --git a/src/test/java/com/auth0/utils/tokens/SignatureVerifierTest.java b/src/test/java/com/auth0/utils/tokens/SignatureVerifierTest.java index 5737015f6..443a99ddd 100644 --- a/src/test/java/com/auth0/utils/tokens/SignatureVerifierTest.java +++ b/src/test/java/com/auth0/utils/tokens/SignatureVerifierTest.java @@ -4,11 +4,9 @@ import com.auth0.exception.PublicKeyProviderException; import com.auth0.jwt.exceptions.AlgorithmMismatchException; import com.auth0.jwt.interfaces.DecodedJWT; -import org.bouncycastle.util.io.pem.PemReader; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; +import org.junit.jupiter.api.Test; +import java.io.BufferedReader; import java.io.FileInputStream; import java.io.FileReader; import java.io.IOException; @@ -20,9 +18,12 @@ import java.security.interfaces.RSAPublicKey; import java.security.spec.EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; +import java.util.Base64; import java.util.Scanner; -import static org.hamcrest.CoreMatchers.*; +import static com.auth0.AssertsUtil.verifyThrows; +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.MatcherAssert.assertThat; public class SignatureVerifierTest { @@ -34,48 +35,37 @@ public class SignatureVerifierTest { private static final String RS_PUBLIC_KEY = "src/test/resources/keys/public-rsa.pem"; private static final String RS_PUBLIC_KEY_BAD = "src/test/resources/keys/bad-public-rsa.pem"; - @SuppressWarnings("deprecation") - @Rule - public ExpectedException exception = ExpectedException.none(); - @Test public void failsWhenAlgorithmIsNotExpected() { - exception.expect(IdTokenValidationException.class); - exception.expectMessage("Signature algorithm of \"none\" is not supported. Expected the ID token to be signed with \"HS256\""); - exception.expectCause(isA(AlgorithmMismatchException.class)); - - SignatureVerifier verifier = SignatureVerifier.forHS256("secret"); - verifier.verifySignature(NONE_JWT); + verifyThrows(IdTokenValidationException.class, + () -> SignatureVerifier.forHS256("secret") + .verifySignature(NONE_JWT), + "Signature algorithm of \"none\" is not supported. Expected the ID token to be signed with \"HS256\""); } @Test public void failsWhenTokenCannotBeDecoded() { - exception.expect(IdTokenValidationException.class); - exception.expectMessage("ID token could not be decoded"); - - SignatureVerifier verifier = SignatureVerifier.forHS256("secret"); - verifier.verifySignature("boom"); + verifyThrows(IdTokenValidationException.class, + () -> SignatureVerifier.forHS256("secret") + .verifySignature("boom"), + "ID token could not be decoded"); } @Test public void failsWhenAlgorithmRS256IsNotExpected() { - exception.expect(IdTokenValidationException.class); - exception.expectMessage("Signature algorithm of \"RS256\" is not supported. Expected the ID token to be signed with \"HS256\""); - exception.expectCause(isA(AlgorithmMismatchException.class)); - - SignatureVerifier verifier = SignatureVerifier.forHS256("secret"); - verifier.verifySignature(RS_JWT); + verifyThrows(IdTokenValidationException.class, + () -> SignatureVerifier.forHS256("secret") + .verifySignature(RS_JWT), + "Signature algorithm of \"RS256\" is not supported. Expected the ID token to be signed with \"HS256\""); } @Test - public void failsWhenAlgorithmHS256IsNotExpected() throws Exception { - exception.expect(IdTokenValidationException.class); - exception.expectMessage("Signature algorithm of \"HS256\" is not supported. Expected the ID token to be signed with \"RS256\""); - exception.expectCause(isA(AlgorithmMismatchException.class)); - - SignatureVerifier verifier = SignatureVerifier.forRS256(getRSProvider(RS_PUBLIC_KEY)); - - verifier.verifySignature(HS_JWT); + public void failsWhenAlgorithmHS256IsNotExpected() { + IdTokenValidationException e = verifyThrows(IdTokenValidationException.class, + () -> SignatureVerifier.forHS256("secret") + .verifySignature(RS_JWT), + "Signature algorithm of \"RS256\" is not supported. Expected the ID token to be signed with \"HS256\""); + assertThat(e.getCause(), instanceOf(AlgorithmMismatchException.class)); } @Test @@ -96,15 +86,14 @@ public void succeedsAndIgnoresExpiredTokenException() { @Test public void failsWithInvalidSignatureHS256Token() { - exception.expect(IdTokenValidationException.class); - exception.expectMessage("Invalid ID token signature"); - - SignatureVerifier verifier = SignatureVerifier.forHS256("badsecret"); - verifier.verifySignature(HS_JWT); + verifyThrows(IdTokenValidationException.class, + () -> SignatureVerifier.forHS256("badsecret") + .verifySignature(HS_JWT), + "Invalid ID token signature"); } @Test - public void succeedsWithValidSignatureRS256Token() throws Exception { + public void succeedsWithValidSignatureRS256Token() { SignatureVerifier verifier = SignatureVerifier.forRS256(getRSProvider(RS_PUBLIC_KEY)); DecodedJWT decodedJWT = verifier.verifySignature(RS_JWT); @@ -112,35 +101,33 @@ public void succeedsWithValidSignatureRS256Token() throws Exception { } @Test - public void failsWithInvalidSignatureRS256Token() throws Exception { - exception.expect(IdTokenValidationException.class); - exception.expectMessage("Invalid ID token signature"); - SignatureVerifier verifier = SignatureVerifier.forRS256(getRSProvider(RS_PUBLIC_KEY_BAD)); - DecodedJWT decodedJWT = verifier.verifySignature(RS_JWT); - - assertThat(decodedJWT, notNullValue()); + public void failsWithInvalidSignatureRS256Token() { + verifyThrows(IdTokenValidationException.class, + () -> SignatureVerifier + .forRS256(getRSProvider(RS_PUBLIC_KEY_BAD)) + .verifySignature(RS_JWT), + "Invalid ID token signature"); } @Test public void failsWhenErrorGettingPublicKey() { - exception.expect(IdTokenValidationException.class); - exception.expectCause(isA(PublicKeyProviderException.class)); - exception.expectMessage("Could not find a public key for Key ID (kid) \"abc123\""); - - SignatureVerifier verifier = SignatureVerifier.forRS256(new PublicKeyProvider() { - @Override - public RSAPublicKey getPublicKeyById(String keyId) throws PublicKeyProviderException { - throw new PublicKeyProviderException("error"); - } - }); - verifier.verifySignature(RS_JWT); + verifyThrows(IdTokenValidationException.class, + () -> { + SignatureVerifier.forRS256(new PublicKeyProvider() { + @Override + public RSAPublicKey getPublicKeyById(String keyId) throws PublicKeyProviderException { + throw new PublicKeyProviderException("error"); + } + }).verifySignature(RS_JWT); + }, + "Could not find a public key for Key ID (kid) \"abc123\""); } @Test public void failsWithNullVerifier() { - exception.expect(IllegalArgumentException.class); - exception.expectMessage("'algorithm' cannot be null"); - new NullVerifier(); + verifyThrows(IllegalArgumentException.class, + NullVerifier::new, + "'algorithm' cannot be null!"); } private PublicKeyProvider getRSProvider(String rsaPath) { @@ -158,7 +145,7 @@ public RSAPublicKey getPublicKeyById(String keyId) throws PublicKeyProviderExcep private static RSAPublicKey readPublicKeyFromFile(final String path) throws IOException { Scanner scanner = null; - PemReader pemReader = null; + BufferedReader reader = null; try { scanner = new Scanner(Paths.get(path)); if (scanner.hasNextLine() && scanner.nextLine().startsWith("-----BEGIN CERTIFICATE-----")) { @@ -169,8 +156,15 @@ private static RSAPublicKey readPublicKeyFromFile(final String path) throws IOEx fs.close(); return (RSAPublicKey) key; } else { - pemReader = new PemReader(new FileReader(path)); - byte[] keyBytes = pemReader.readPemObject().getContent(); + reader = new BufferedReader(new FileReader(path)); + StringBuilder pemContent = new StringBuilder(); + String line; + while ((line = reader.readLine()) != null) { + if (!line.startsWith("-----BEGIN") && !line.startsWith("-----END")) { + pemContent.append(line); + } + } + byte[] keyBytes = Base64.getDecoder().decode(pemContent.toString()); KeyFactory kf = KeyFactory.getInstance("RSA"); EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); return (RSAPublicKey) kf.generatePublic(keySpec); @@ -181,8 +175,8 @@ private static RSAPublicKey readPublicKeyFromFile(final String path) throws IOEx if (scanner != null) { scanner.close(); } - if (pemReader != null) { - pemReader.close(); + if (reader != null) { + reader.close(); } } } diff --git a/src/test/resources/auth/add_oob_authenticator_response.json b/src/test/resources/auth/add_oob_authenticator_response.json new file mode 100644 index 000000000..df463c1c2 --- /dev/null +++ b/src/test/resources/auth/add_oob_authenticator_response.json @@ -0,0 +1,8 @@ +{ + "oob_code": "Fe26.2**da6....", + "binding_method":"prompt", + "authenticator_type":"oob", + "oob_channel":"sms", + "recovery_codes":["ABCDEFGDRFK75ABYR7PH8TJA"], + "barcode_uri":"otpauth://..." +} diff --git a/src/test/resources/auth/add_otp_authenticator_response.json b/src/test/resources/auth/add_otp_authenticator_response.json new file mode 100644 index 000000000..f4c71fc7f --- /dev/null +++ b/src/test/resources/auth/add_otp_authenticator_response.json @@ -0,0 +1,6 @@ +{ + "secret": "ABCDEFGMK5CE6WTZKRTTQRKUJVFXOVRF", + "barcode_uri":"otpauth://...", + "authenticator_type":"otp", + "recovery_codes":["ABCDEFGDRFK75ABYR7PH8TJA"] +} diff --git a/src/test/resources/auth/back_channel_authorize_response.json b/src/test/resources/auth/back_channel_authorize_response.json new file mode 100644 index 000000000..bc0649f08 --- /dev/null +++ b/src/test/resources/auth/back_channel_authorize_response.json @@ -0,0 +1,5 @@ +{ + "auth_req_id": "red_id_1", + "expires_in": 300, + "interval": 5 +} diff --git a/src/test/resources/auth/back_channel_login_status_response.json b/src/test/resources/auth/back_channel_login_status_response.json new file mode 100644 index 000000000..bc1676e2c --- /dev/null +++ b/src/test/resources/auth/back_channel_login_status_response.json @@ -0,0 +1,6 @@ +{ + "access_token": "eyJhbGciOiJkaXIi.....", + "id_token": "eyJhbGciOiJSUzI1NiIs.....", + "expires_in": 86400, + "scope": "openid" +} diff --git a/src/test/resources/auth/list_authenticators_response.json b/src/test/resources/auth/list_authenticators_response.json new file mode 100644 index 000000000..27800f194 --- /dev/null +++ b/src/test/resources/auth/list_authenticators_response.json @@ -0,0 +1,26 @@ +[ + { + "id":"recovery-code|dev_DsvzGfZw2Fg5N3rI", + "authenticator_type":"recovery-code", + "active":true + }, + { + "id":"sms|dev_gB342kcL2K22S4yB", + "authenticator_type":"oob", + "oob_channel":"sms", + "name":"+X XXXX1234", + "active":true + }, + { + "id":"sms|dev_gB342kcL2K22S4yB", + "authenticator_type":"oob", + "oob_channel":"sms", + "name":"+X XXXX1234", + "active":false + }, + { + "id":"totp|dev_LJaKaN5O3tjRFOw2", + "authenticator_type":"otp", + "active":true + } +] diff --git a/src/test/resources/auth/mfa_challenge_request_response.json b/src/test/resources/auth/mfa_challenge_request_response.json new file mode 100644 index 000000000..469fc18e0 --- /dev/null +++ b/src/test/resources/auth/mfa_challenge_request_response.json @@ -0,0 +1,5 @@ +{ + "challenge_type":"oob", + "binding_method":"prompt", + "oob_code": "abcde...dasg" +} diff --git a/src/test/resources/auth/pushed_authorization_response.json b/src/test/resources/auth/pushed_authorization_response.json new file mode 100644 index 000000000..ca1a5b744 --- /dev/null +++ b/src/test/resources/auth/pushed_authorization_response.json @@ -0,0 +1,4 @@ +{ + "request_uri": "urn:example:bwc4JK-ESC0w8acc191e-Y1LTC2", + "expires_in": 90 +} diff --git a/src/test/resources/auth/rsa_private_key.pem b/src/test/resources/auth/rsa_private_key.pem new file mode 100644 index 000000000..1427e0d51 --- /dev/null +++ b/src/test/resources/auth/rsa_private_key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC4ZtdaIrd1BPIJ +tfnF0TjIK5inQAXZ3XlCrUlJdP+XHwIRxdv1FsN12XyMYO/6ymLmo9ryoQeIrsXB +XYqlET3zfAY+diwCb0HEsVvhisthwMU4gZQu6TYW2s9LnXZB5rVtcBK69hcSlA2k +ZudMZWxZcj0L7KMfO2rIvaHw/qaVOE9j0T257Z8Kp2CLF9MUgX0ObhIsdumFRLaL +DvDUmBPr2zuh/34j2XmWwn1yjN/WvGtdfhXW79Ki1S40HcWnygHgLV8sESFKUxxQ +mKvPUTwDOIwLFL5WtE8Mz7N++kgmDcmWMCHc8kcOIu73Ta/3D4imW7VbKgHZo9+K +3ESFE3RjAgMBAAECggEBAJTEIyjMqUT24G2FKiS1TiHvShBkTlQdoR5xvpZMlYbN +tVWxUmrAGqCQ/TIjYnfpnzCDMLhdwT48Ab6mQJw69MfiXwc1PvwX1e9hRscGul36 +ryGPKIVQEBsQG/zc4/L2tZe8ut+qeaK7XuYrPp8bk/X1e9qK5m7j+JpKosNSLgJj +NIbYsBkG2Mlq671irKYj2hVZeaBQmWmZxK4fw0Istz2WfN5nUKUeJhTwpR+JLUg4 +ELYYoB7EO0Cej9UBG30hbgu4RyXA+VbptJ+H042K5QJROUbtnLWuuWosZ5ATldwO +u03dIXL0SH0ao5NcWBzxU4F2sBXZRGP2x/jiSLHcqoECgYEA4qD7mXQpu1b8XO8U +6abpKloJCatSAHzjgdR2eRDRx5PMvloipfwqA77pnbjTUFajqWQgOXsDTCjcdQui +wf5XAaWu+TeAVTytLQbSiTsBhrnoqVrr3RoyDQmdnwHT8aCMouOgcC5thP9vQ8Us +rVdjvRRbnJpg3BeSNimH+u9AHgsCgYEA0EzcbOltCWPHRAY7B3Ge/AKBjBQr86Kv +TdpTlxePBDVIlH+BM6oct2gaSZZoHbqPjbq5v7yf0fKVcXE4bSVgqfDJ/sZQu9Lp +PTeV7wkk0OsAMKk7QukEpPno5q6tOTNnFecpUhVLLlqbfqkB2baYYwLJR3IRzboJ +FQbLY93E8gkCgYB+zlC5VlQbbNqcLXJoImqItgQkkuW5PCgYdwcrSov2ve5r/Acz +FNt1aRdSlx4176R3nXyibQA1Vw+ztiUFowiP9WLoM3PtPZwwe4bGHmwGNHPIfwVG +m+exf9XgKKespYbLhc45tuC08DATnXoYK7O1EnUINSFJRS8cezSI5eHcbQKBgQDC +PgqHXZ2aVftqCc1eAaxaIRQhRmY+CgUjumaczRFGwVFveP9I6Gdi+Kca3DE3F9Pq +PKgejo0SwP5vDT+rOGHN14bmGJUMsX9i4MTmZUZ5s8s3lXh3ysfT+GAhTd6nKrIE +kM3Nh6HWFhROptfc6BNusRh1kX/cspDplK5x8EpJ0QKBgQDWFg6S2je0KtbV5PYe +RultUEe2C0jYMDQx+JYxbPmtcopvZQrFEur3WKVuLy5UAy7EBvwMnZwIG7OOohJb +vkSpADK6VPn9lbqq7O8cTedEHttm6otmLt8ZyEl3hZMaL3hbuRj6ysjmoFKx6CrX +rK0/Ikt5ybqUzKCMJZg2VKGTxg== +-----END PRIVATE KEY----- diff --git a/src/test/resources/auth/rsa_public_key.pem b/src/test/resources/auth/rsa_public_key.pem new file mode 100644 index 000000000..e8d628859 --- /dev/null +++ b/src/test/resources/auth/rsa_public_key.pem @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuGbXWiK3dQTyCbX5xdE4 +yCuYp0AF2d15Qq1JSXT/lx8CEcXb9RbDddl8jGDv+spi5qPa8qEHiK7FwV2KpRE9 +83wGPnYsAm9BxLFb4YrLYcDFOIGULuk2FtrPS512Qea1bXASuvYXEpQNpGbnTGVs +WXI9C+yjHztqyL2h8P6mlThPY9E9ue2fCqdgixfTFIF9Dm4SLHbphUS2iw7w1JgT +69s7of9+I9l5lsJ9cozf1rxrXX4V1u/SotUuNB3Fp8oB4C1fLBEhSlMcUJirz1E8 +AziMCxS+VrRPDM+zfvpIJg3JljAh3PJHDiLu902v9w+Iplu1WyoB2aPfitxEhRN0 +YwIDAQAB +-----END PUBLIC KEY----- diff --git a/src/test/resources/auth/sign_up_username.json b/src/test/resources/auth/sign_up_username.json index 6baee7030..83315e25e 100644 --- a/src/test/resources/auth/sign_up_username.json +++ b/src/test/resources/auth/sign_up_username.json @@ -2,5 +2,6 @@ "_id": "58457fe6b27", "email_verified": false, "email": "me@auth0.com", - "username": "me" -} \ No newline at end of file + "username": "me", + "phone_number": "1234567890" +} diff --git a/src/test/resources/mgmt/authenticator_method_by_id.json b/src/test/resources/mgmt/authenticator_method_by_id.json new file mode 100644 index 000000000..b76986a1e --- /dev/null +++ b/src/test/resources/mgmt/authenticator_method_by_id.json @@ -0,0 +1,7 @@ +{ + "id":"email|dev_7o0sei0Q5FJNLfk1", + "type":"email", + "confirmed":true, + "email":"****@pmes****", + "created_at":"2023-01-19T15:26:28.887Z" +} diff --git a/src/test/resources/mgmt/authenticator_method_create.json b/src/test/resources/mgmt/authenticator_method_create.json new file mode 100644 index 000000000..172cdc4a8 --- /dev/null +++ b/src/test/resources/mgmt/authenticator_method_create.json @@ -0,0 +1,6 @@ +{ + "type":"email", + "created_at":"2023-01-19T15:21:44.014Z", + "email":"temp12@temp.com", + "id":"email|dev_CgJUhSQ6jqPiQAsJ" +} diff --git a/src/test/resources/mgmt/authenticator_method_list.json b/src/test/resources/mgmt/authenticator_method_list.json new file mode 100644 index 000000000..119011a1d --- /dev/null +++ b/src/test/resources/mgmt/authenticator_method_list.json @@ -0,0 +1,43 @@ +[ + { + "id": "phone|123", + "type": "phone", + "confirmed": true, + "phone_number": "XXXXXXXX0000", + "created_at": "2023-02-01T18:44:46.483Z", + "last_auth_at": "2023-02-07T20:29:33.547Z", + "preferred_authentication_method": "sms", + "credential_device_type": "single_device", + "credential_backed_up": true, + "identity_user_id": "identityId", + "user_agent": "userAgent", + "authentication_methods": [ + { + "id": "sms|id", + "type": "sms" + } + ] + }, + { + "id": "webauthn-platform|id", + "type": "webauthn-platform", + "confirmed": true, + "name": "name", + "created_at": "2023-02-01T18:44:50.304Z", + "last_auth_at": "2023-02-01T18:45:10.817Z", + "key_id": "xxxxxx-xxxx_xxxxxxxxxxxxxxx", + "public_key": "pubkey", + "relying_party_identifier": "tenant.auth0.com" + }, + { + "id": "webauthn-platform|id", + "type": "webauthn-platform", + "confirmed": true, + "name": "name", + "created_at": "2023-03-14T20:13:25.541Z", + "last_auth_at": "2023-03-14T20:13:32.834Z", + "key_id": "keyid", + "public_key": "pubkey", + "relying_party_identifier": "tenant.auth0.com" + } +] diff --git a/src/test/resources/mgmt/authenticator_method_paged_list.json b/src/test/resources/mgmt/authenticator_method_paged_list.json new file mode 100644 index 000000000..70ac22333 --- /dev/null +++ b/src/test/resources/mgmt/authenticator_method_paged_list.json @@ -0,0 +1,22 @@ +{ + "authenticators": [ + { + "id": "phone|id", + "type": "phone", + "confirmed": true, + "phone_number": "XXXXXXXX0000", + "created_at": "2023-02-01T18:44:46.483Z", + "last_auth_at": "2023-02-07T20:29:33.547Z", + "preferred_authentication_method": "sms", + "authentication_methods": [ + { + "id": "sms|id", + "type": "sms" + } + ] + } + ], + "total": 3, + "start": 0, + "limit": 1 +} diff --git a/src/test/resources/mgmt/authenticator_method_update.json b/src/test/resources/mgmt/authenticator_method_update.json new file mode 100644 index 000000000..b0e66c214 --- /dev/null +++ b/src/test/resources/mgmt/authenticator_method_update.json @@ -0,0 +1,8 @@ +[ + { + "id":"email|dev_o05Io01uPXyvi87E", + "type":"email", + "email":"semp@pmes.com", + "created_at":"2023-01-19T15:23:29.156Z" + } +] diff --git a/src/test/resources/mgmt/authenticator_method_update_by_id.json b/src/test/resources/mgmt/authenticator_method_update_by_id.json new file mode 100644 index 000000000..ed18fb154 --- /dev/null +++ b/src/test/resources/mgmt/authenticator_method_update_by_id.json @@ -0,0 +1,7 @@ +{ + "type":"email", + "name":"123temp@temp123.com", + "created_at":"2023-01-19T15:26:28.887Z", + "email":"semp@pmes.com", + "id":"email|dev_7o0sei0Q5FJNLfk1" +} diff --git a/src/test/resources/mgmt/breached_password_settings.json b/src/test/resources/mgmt/breached_password_settings.json index ca9531c01..b3c1bce9f 100644 --- a/src/test/resources/mgmt/breached_password_settings.json +++ b/src/test/resources/mgmt/breached_password_settings.json @@ -8,5 +8,12 @@ "immediately", "weekly" ], - "method": "standard" + "method": "standard", + "stage": { + "pre-user-registration": { + "shields": [ + "admin_notification" + ] + } + } } diff --git a/src/test/resources/mgmt/client.json b/src/test/resources/mgmt/client.json index 54307b151..967c9104c 100644 --- a/src/test/resources/mgmt/client.json +++ b/src/test/resources/mgmt/client.json @@ -59,5 +59,44 @@ "team_id": "9JA89QQLNQ", "app_bundle_identifier": "com.my.bundle.id" } + }, + "client_authentication_methods": { + "private_key_jwt": { + "credentials": [ { + "id": "cred_abc" + }] + }, + "self_signed_tls_client_auth": { + "credentials": [ { + "id": "cred_123" + }] + }, + "tls_client_auth": { + "credentials": [ { + "id": "cred_789" + }] + } + }, + "signed_request_object": { + "credentials": [ + { + "id": "cred_id", + "credential_type": "public_key", + "kid": "cred_kid", + "alg": "RS256", + "name": "My JAR credential", + "created_at": "2024-03-14T11:34:28.893Z", + "updated_at": "2024-03-14T11:34:28.893Z" + } + ] + }, + "compliance_level": "fapi1_adv_pkj_par", + "require_proof_of_possession": true, + "token_quota": { + "client_credentials": { + "per_day": 100, + "per_hour": 20, + "enforce": true + } } -} \ No newline at end of file +} diff --git a/src/test/resources/mgmt/client_credential.json b/src/test/resources/mgmt/client_credential.json new file mode 100644 index 000000000..fa0f0fc2b --- /dev/null +++ b/src/test/resources/mgmt/client_credential.json @@ -0,0 +1,11 @@ +{ + "id": "cred_asqwXXXIIadqq2T3zAXPwv", + "name": "new cred", + "credential_type": "public_key", + "kid": "eKtBStP7BN2NiaoVrNGzb0QaRl4HlzyH1Lp00JB6Xj0", + "alg": "RS256", + "thumbprint": "thumb", + "created_at": "2023-04-13T16:18:01.481Z", + "updated_at": "2023-04-13T16:18:01.481Z", + "expires_at": "2023-04-13T16:19:00.349Z" +} diff --git a/src/test/resources/mgmt/client_credential_list.json b/src/test/resources/mgmt/client_credential_list.json new file mode 100644 index 000000000..59fa510de --- /dev/null +++ b/src/test/resources/mgmt/client_credential_list.json @@ -0,0 +1,13 @@ +[ + { + "id": "cred_asqwdTaebdqq2T3zAXPwv", + "name": "new cred", + "credential_type": "public_key", + "kid": "eKtBStP7BN2NV1MVrNGzb0QaRp0uHlzyH1Lje9JB6Xj0", + "alg": "RS256", + "thumbprint": "thumb", + "created_at": "2023-04-13T16:18:01.481Z", + "updated_at": "2023-04-13T16:18:01.481Z", + "expires_at": "2023-04-13T16:19:00.349Z" + } +] diff --git a/src/test/resources/mgmt/clients_list.json b/src/test/resources/mgmt/clients_list.json index a62d12663..208b5ff5a 100644 --- a/src/test/resources/mgmt/clients_list.json +++ b/src/test/resources/mgmt/clients_list.json @@ -41,7 +41,7 @@ "is_heroku_app": false, "tenant": "auth0", "global": false, - "cross_origin_auth": false, + "cross_origin_authentication": false, "cross_origin_loc": "https://auth0.com/auth/callback-cross-auth", "addons": { "rms": {}, @@ -72,6 +72,13 @@ "team_id": "9JA89QQLNQ", "app_bundle_identifier": "com.my.bundle.id" } + }, + "token_quota": { + "client_credentials": { + "per_day": 100, + "per_hour": 20, + "enforce": true + } } }, { diff --git a/src/test/resources/mgmt/connection.json b/src/test/resources/mgmt/connection.json index b94306245..f2f51e098 100644 --- a/src/test/resources/mgmt/connection.json +++ b/src/test/resources/mgmt/connection.json @@ -8,6 +8,8 @@ "ScKKdrpyUwfkhOQP6KXItH32INgZf7Rb" ], "metadata": { - "key": "value" - } -} \ No newline at end of file + "key": "value" + }, + "is_domain_connection": true, + "show_as_button": true +} diff --git a/src/test/resources/mgmt/connection_key.json b/src/test/resources/mgmt/connection_key.json new file mode 100644 index 000000000..0e4a30720 --- /dev/null +++ b/src/test/resources/mgmt/connection_key.json @@ -0,0 +1,25 @@ +[ + { + "kid": "kid-1", + "algorithm": "RS256", + "key_use": "signing", + "subject_dn": "/CN=cajwt", + "cert": "-----BEGIN CERTIFICATE-----\r\ncert-key-1\r\n-----END CERTIFICATE-----\r\n", + "fingerprint": "F1", + "thumbprint": "example-print", + "pkcs": "-----BEGIN PKCS7-----\r\npkcs-1\r\n-----END PKCS7-----\r\n", + "current": true, + "current_since": "2025-05-29T13:17:24.850Z" + }, + { + "kid": "kid-2", + "algorithm": "RS256", + "key_use": "signing", + "subject_dn": "/CN=cajwt", + "cert": "-----BEGIN CERTIFICATE-----\r\ncert-key-2\r\n-----END CERTIFICATE-----\r\n", + "fingerprint": "F2", + "thumbprint": "example-print", + "pkcs": "-----BEGIN PKCS7-----\r\npkcs-2\r\n-----END PKCS7-----\r\n", + "next": true + } +] diff --git a/src/test/resources/mgmt/connection_scim_configuration.json b/src/test/resources/mgmt/connection_scim_configuration.json new file mode 100644 index 000000000..e975aba6f --- /dev/null +++ b/src/test/resources/mgmt/connection_scim_configuration.json @@ -0,0 +1,19 @@ +{ + "tenant_name": "dev-1", + "connection_id": "con_0000000000000001", + "connection_name": "New Connection", + "strategy": "okta", + "mapping": [ + { + "scim": "userName", + "auth0": "preferred_username" + }, + { + "scim": "emails[primary eq true].value", + "auth0": "email" + } + ], + "updated_on": "2025-01-22T11:56:24.461Z", + "created_at": "2025-01-22T11:56:24.461Z", + "user_id_attribute": "externalId" +} diff --git a/src/test/resources/mgmt/connection_scim_token.json b/src/test/resources/mgmt/connection_scim_token.json new file mode 100644 index 000000000..13de59eed --- /dev/null +++ b/src/test/resources/mgmt/connection_scim_token.json @@ -0,0 +1,9 @@ +{ + "token_id": "tok_000000001", + "token": "tok_iwioqiwoqoqiwqoiwqwi", + "scopes": [ + "get:users" + ], + "created_at": "2025-01-23T12:34:46.321Z", + "valid_until": "2025-01-23T12:51:26.321Z" +} diff --git a/src/test/resources/mgmt/connection_scim_tokens.json b/src/test/resources/mgmt/connection_scim_tokens.json new file mode 100644 index 000000000..421689d93 --- /dev/null +++ b/src/test/resources/mgmt/connection_scim_tokens.json @@ -0,0 +1,21 @@ +[ + { + "token_id": "tok_000000001", + "created_at": "2025-01-23T12:34:46.321Z", + "scopes": [ + "get:users" + ], + "valid_until": "2025-01-23T12:51:26.321Z" + }, + { + "token_id": "tok_000000002", + "created_at": "2025-01-22T12:09:23.313Z", + "scopes": [ + "get:users", + "post:users", + "patch:users", + "delete:users", + "put:users" + ] + } +] diff --git a/src/test/resources/mgmt/custom_text_prompt.json b/src/test/resources/mgmt/custom_text_prompt.json new file mode 100644 index 000000000..dd14ae925 --- /dev/null +++ b/src/test/resources/mgmt/custom_text_prompt.json @@ -0,0 +1,5 @@ +{ + "signup": { + "description": "Sign up to access amazing features for my login domain" + } +} diff --git a/src/test/resources/mgmt/default_connection_scim_configuration.json b/src/test/resources/mgmt/default_connection_scim_configuration.json new file mode 100644 index 000000000..ceccc8793 --- /dev/null +++ b/src/test/resources/mgmt/default_connection_scim_configuration.json @@ -0,0 +1,12 @@ +{ + "mapping": [ + { + "auth0": "preferred_username", + "scim": "userName" + }, + { + "auth0": "email", + "scim": "emails[primary eq true].value" + } + ] +} diff --git a/src/test/resources/mgmt/enabled_clients_for_connection.json b/src/test/resources/mgmt/enabled_clients_for_connection.json new file mode 100644 index 000000000..d45d04a29 --- /dev/null +++ b/src/test/resources/mgmt/enabled_clients_for_connection.json @@ -0,0 +1,11 @@ +{ + "clients": [ + { + "client_id": "client-1" + }, + { + "client_id": "client-2" + } + ], + "next": "next" +} diff --git a/src/test/resources/mgmt/encryption_key.json b/src/test/resources/mgmt/encryption_key.json new file mode 100644 index 000000000..8c11c21e2 --- /dev/null +++ b/src/test/resources/mgmt/encryption_key.json @@ -0,0 +1,9 @@ +{ + "kid": "kid", + "type": "tenant-master-key", + "state": "active", + "created_at": "2024-10-16T10:50:44.107Z", + "updated_at": "2024-10-24T06:47:24.899Z", + "parent_kid": "pkid", + "public_key": "pkey" +} diff --git a/src/test/resources/mgmt/encryption_keys_list.json b/src/test/resources/mgmt/encryption_keys_list.json new file mode 100644 index 000000000..fe5fc2d28 --- /dev/null +++ b/src/test/resources/mgmt/encryption_keys_list.json @@ -0,0 +1,29 @@ +[ + { + "kid": "kid-1", + "type": "customer-provided-root-key", + "state": "pre-activation", + "created_at": "2024-10-24T08:02:18.029Z", + "updated_at": "2024-10-24T08:02:18.029Z", + "parent_kid": null, + "public_key": null + }, + { + "kid": "kid-2", + "type": "tenant-master-key", + "state": "active", + "created_at": "2024-10-24T06:47:23.749Z", + "updated_at": "2024-10-24T06:47:23.749Z", + "parent_kid": "pkid-1", + "public_key": null + }, + { + "kid": "kid-3", + "type": "tenant-master-key", + "state": "destroyed", + "created_at": "2024-10-16T10:50:44.107Z", + "updated_at": "2024-10-24T06:47:24.899Z", + "parent_kid": "pkid-2", + "public_key": null + } +] diff --git a/src/test/resources/mgmt/log_stream.json b/src/test/resources/mgmt/log_stream.json index cb7bdccd9..aeab7dd3c 100644 --- a/src/test/resources/mgmt/log_stream.json +++ b/src/test/resources/mgmt/log_stream.json @@ -9,5 +9,15 @@ "httpContentType": "application/json", "httpAuthorization": "abc123", "httpEndpoint": "https//me.org" - } + }, + "filters": [ + { + "type": "category", + "name": "auth.ancillary.success" + }, + { + "type": "category", + "name": "auth.ancillary.fail" + } + ] } diff --git a/src/test/resources/mgmt/log_streams_list.json b/src/test/resources/mgmt/log_streams_list.json index 2f94be264..eaf14c8fb 100644 --- a/src/test/resources/mgmt/log_streams_list.json +++ b/src/test/resources/mgmt/log_streams_list.json @@ -9,7 +9,17 @@ "httpContentType": "application/json", "httpAuthorization": "abc123", "httpEndpoint": "https//me.org" - } + }, + "filters": [ + { + "type": "category", + "name": "auth.ancillary.success" + }, + { + "type": "category", + "name": "auth.ancillary.fail" + } + ] }, { "id": "456", @@ -21,6 +31,16 @@ "datadogApiKey": "abc123", "httpAuthorization": "abc123", "httpEndpoint": "https//me.org" - } + }, + "filters": [ + { + "type": "category", + "name": "auth.ancillary.success" + }, + { + "type": "category", + "name": "auth.ancillary.fail" + } + ] } ] diff --git a/src/test/resources/mgmt/network_acls.json b/src/test/resources/mgmt/network_acls.json new file mode 100644 index 000000000..d618014d9 --- /dev/null +++ b/src/test/resources/mgmt/network_acls.json @@ -0,0 +1,20 @@ +{ + "description": "Log America and Canada all the time.", + "active": true, + "priority": 1, + "rule": { + "match": { + "geo_country_codes": [ + "US", + "CA" + ] + }, + "scope": "authentication", + "action": { + "log": true + } + }, + "created_at": "2025-03-17T12:31:57.782Z", + "updated_at": "2025-03-17T12:31:57.782Z", + "id": "acl_1" +} diff --git a/src/test/resources/mgmt/network_acls_list.json b/src/test/resources/mgmt/network_acls_list.json new file mode 100644 index 000000000..d9496a31a --- /dev/null +++ b/src/test/resources/mgmt/network_acls_list.json @@ -0,0 +1,47 @@ +{ + "total": 14, + "start": 0, + "length": 14, + "network_acls": [ + { + "description": "Log America and Canada all the time.", + "active": true, + "priority": 1, + "rule": { + "match": { + "geo_country_codes": [ + "US", + "CA" + ] + }, + "scope": "authentication", + "action": { + "log": true + } + }, + "created_at": "2025-03-17T12:31:57.782Z", + "updated_at": "2025-03-17T12:31:57.782Z", + "id": "acl_1" + }, + { + "description": "Test Desc - 1", + "active": true, + "priority": 10, + "rule": { + "match": { + "ipv4_cidrs": [ + "198.51.100.48", + "10.0.0.0/24" + ] + }, + "scope": "management", + "action": { + "block": true + } + }, + "created_at": "2025-06-10T06:18:10.277Z", + "updated_at": "2025-06-10T06:18:10.277Z", + "id": "acl_2" + } + ] +} diff --git a/src/test/resources/mgmt/organization.json b/src/test/resources/mgmt/organization.json index 3782c22c7..1453d8f94 100644 --- a/src/test/resources/mgmt/organization.json +++ b/src/test/resources/mgmt/organization.json @@ -17,5 +17,12 @@ "connection_id": "con-1", "assign_membership_on_login": false } - ] + ], + "token_quota": { + "client_credentials": { + "per_day": 100, + "per_hour": 20, + "enforce": true + } + } } diff --git a/src/test/resources/mgmt/organization_client_grant.json b/src/test/resources/mgmt/organization_client_grant.json new file mode 100644 index 000000000..83f6255eb --- /dev/null +++ b/src/test/resources/mgmt/organization_client_grant.json @@ -0,0 +1,9 @@ +{ + "id": "1", + "client_id": "clientId1", + "audience": "audience1", + "scope": [ + "openid", + "profile" + ] +} diff --git a/src/test/resources/mgmt/organization_client_grants.json b/src/test/resources/mgmt/organization_client_grants.json new file mode 100644 index 000000000..8f5eaec13 --- /dev/null +++ b/src/test/resources/mgmt/organization_client_grants.json @@ -0,0 +1,17 @@ +[ + { + "id": "cgr_4pI9a42haOLLWnwq", + "client_id": "client-id", + "audience": "https://api-identifier", + "scope": [ + "update:items", + "read:messages" + ] + }, + { + "id": "cgr_D018f9kmBmwbZod", + "client_id": "client-id", + "audience": "https://api-identifier", + "scope": [] + } +] diff --git a/src/test/resources/mgmt/organization_client_grants_paged_list.json b/src/test/resources/mgmt/organization_client_grants_paged_list.json new file mode 100644 index 000000000..fe52b21b6 --- /dev/null +++ b/src/test/resources/mgmt/organization_client_grants_paged_list.json @@ -0,0 +1,15 @@ +{ + "total": 13, + "start": 0, + "limit": 1, + "client_grants": [ + { + "id": "cgr_3aidkk3skLVOM3Ay7", + "client_id": "client-id", + "audience": "https://api-identifier/", + "scope": [ + "read:messages" + ] + } + ] +} diff --git a/src/test/resources/mgmt/organization_connection.json b/src/test/resources/mgmt/organization_connection.json index fc1c51418..32d043905 100644 --- a/src/test/resources/mgmt/organization_connection.json +++ b/src/test/resources/mgmt/organization_connection.json @@ -1,4 +1,5 @@ { "connection_id": "con_At4BWXhV3lKv82jd", - "assign_membership_on_login": false + "assign_membership_on_login": false, + "show_as_button": true } diff --git a/src/test/resources/mgmt/organization_connections_list.json b/src/test/resources/mgmt/organization_connections_list.json index 9c602251b..e0bff656b 100644 --- a/src/test/resources/mgmt/organization_connections_list.json +++ b/src/test/resources/mgmt/organization_connections_list.json @@ -2,6 +2,7 @@ { "connection_id": "con_At4BWXhV3lKv82jd", "assign_membership_on_login": false, + "show_as_button": true, "connection": { "name": "google-oauth2", "strategy": "google-oauth2" @@ -10,6 +11,7 @@ { "connection_id": "con_kai93HmEDCs8ai3d", "assign_membership_on_login": true, + "show_as_button": true, "connection": { "name": "Username-Password-Authentication", "strategy": "auth0" diff --git a/src/test/resources/mgmt/organization_connections_paged_list.json b/src/test/resources/mgmt/organization_connections_paged_list.json index 4772fe118..7ecbe34c9 100644 --- a/src/test/resources/mgmt/organization_connections_paged_list.json +++ b/src/test/resources/mgmt/organization_connections_paged_list.json @@ -3,6 +3,7 @@ { "connection_id": "con_At4BWXhV3lKv82jd", "assign_membership_on_login": false, + "show_as_button": true, "connection": { "name": "google-oauth2", "strategy": "google-oauth2" @@ -11,6 +12,7 @@ { "connection_id": "con_kai93HmEDCs8ai3d", "assign_membership_on_login": true, + "show_as_button": true, "connection": { "name": "Username-Password-Authentication", "strategy": "auth0" diff --git a/src/test/resources/mgmt/organizations_list.json b/src/test/resources/mgmt/organizations_list.json index 504f7fd21..2b765439b 100644 --- a/src/test/resources/mgmt/organizations_list.json +++ b/src/test/resources/mgmt/organizations_list.json @@ -12,6 +12,13 @@ }, "metadata": { "key1": "val1" + }, + "token_quota": { + "client_credentials": { + "per_day": 100, + "per_hour": 20, + "enforce": true + } } }, { diff --git a/src/test/resources/mgmt/partials_prompt.json b/src/test/resources/mgmt/partials_prompt.json new file mode 100644 index 000000000..2c63c0851 --- /dev/null +++ b/src/test/resources/mgmt/partials_prompt.json @@ -0,0 +1,2 @@ +{ +} diff --git a/src/test/resources/mgmt/prompt.json b/src/test/resources/mgmt/prompt.json new file mode 100644 index 000000000..5dd9655c1 --- /dev/null +++ b/src/test/resources/mgmt/prompt.json @@ -0,0 +1,5 @@ +{ + "universal_login_experience": "new", + "identifier_first": true, + "webauthn_platform_first_factor": true +} diff --git a/src/test/resources/mgmt/rate_limit_error.json b/src/test/resources/mgmt/rate_limit_error.json new file mode 100644 index 000000000..27478a620 --- /dev/null +++ b/src/test/resources/mgmt/rate_limit_error.json @@ -0,0 +1,6 @@ +{ + "statusCode":429, + "error":"Too Many Requests", + "message":"Global limit has been reached", + "errorCode":"too_many_requests" +} diff --git a/src/test/resources/mgmt/refresh_token.json b/src/test/resources/mgmt/refresh_token.json new file mode 100644 index 000000000..9a3adca50 --- /dev/null +++ b/src/test/resources/mgmt/refresh_token.json @@ -0,0 +1,25 @@ +{ + "id": "tokenId1", + "user_id": "userId1", + "created_at": "2024-06-26T09:10:26.643Z", + "idle_expires_at": "2024-06-26T09:10:27.131Z", + "expires_at": "2024-07-03T09:10:26.643Z", + "device": { + "initial_asn": "1234", + "initial_ip": "203.0.113.1", + "initial_user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36", + "last_user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36", + "last_ip": "203.0.113.1", + "last_asn": "1234" + }, + "client_id": "clientId1", + "session_id": "sessionId1", + "rotating": false, + "resource_servers": [ + { + "audience": "https://api.example.com", + "scopes": "offline_access" + } + ], + "last_exchanged_at": "2024-07-03T09:10:26.643Z" +} diff --git a/src/test/resources/mgmt/resource_server.json b/src/test/resources/mgmt/resource_server.json index 1a84daae3..75284b5a4 100644 --- a/src/test/resources/mgmt/resource_server.json +++ b/src/test/resources/mgmt/resource_server.json @@ -21,5 +21,24 @@ } ], "is_system": true, - "enforce_policies": false -} \ No newline at end of file + "enforce_policies": false, + "consent_policy": "transactional-authorization-with-mfa", + "authorization_details": [{ + "type": "payment" + }, { + "type": "my custom type" + }], + "token_encryption": { + "format": "compact-nested-jwe", + "encryption_key": { + "name": "my JWE public key", + "kid": "my kid", + "alg": "RSA-OAEP-256", + "thumbprint_sha256": "thumbprint" + } + }, + "proof_of_possession": { + "mechanism": "mtls", + "required": true + } +} diff --git a/src/test/resources/mgmt/rotate_key.json b/src/test/resources/mgmt/rotate_key.json new file mode 100644 index 000000000..706ea8235 --- /dev/null +++ b/src/test/resources/mgmt/rotate_key.json @@ -0,0 +1,4 @@ +{ + "kid": "kid-1", + "cert": "-----BEGIN CERTIFICATE-----cert-key-----END CERTIFICATE-----" +} diff --git a/src/test/resources/mgmt/self_service_profile.json b/src/test/resources/mgmt/self_service_profile.json new file mode 100644 index 000000000..6c090caa4 --- /dev/null +++ b/src/test/resources/mgmt/self_service_profile.json @@ -0,0 +1,21 @@ +{ + "id": "id", + "name": "Test", + "description": "This is for Test", + "user_attributes": [ + { + "name": "Phone", + "description": "This is Phone Number", + "is_optional": true + } + ], + "branding": { + "logo_url": "https://www.google.com", + "colors": { + "primary": "#ffffff" + } + }, + "allowed_strategies": [ + "oidc" + ] +} diff --git a/src/test/resources/mgmt/self_service_profile_custom_text.json b/src/test/resources/mgmt/self_service_profile_custom_text.json new file mode 100644 index 000000000..ef8aac8d0 --- /dev/null +++ b/src/test/resources/mgmt/self_service_profile_custom_text.json @@ -0,0 +1,3 @@ +{ + "introduction": "Welcome! With only a few steps" +} diff --git a/src/test/resources/mgmt/self_service_profile_response.json b/src/test/resources/mgmt/self_service_profile_response.json new file mode 100644 index 000000000..46b5bcd8e --- /dev/null +++ b/src/test/resources/mgmt/self_service_profile_response.json @@ -0,0 +1,23 @@ +{ + "id": "id", + "name": "Test", + "description": "This is a Test", + "user_attributes": [ + { + "name": "Phone", + "description": "This is Phone Number", + "is_optional": true + } + ], + "allowed_strategies": [ + "oidc" + ], + "created_at": "2024-12-20T09:32:13.885Z", + "updated_at": "2024-12-20T09:32:13.885Z", + "branding": { + "logo_url": "https://www.google.com", + "colors": { + "primary": "#ffffff" + } + } +} diff --git a/src/test/resources/mgmt/self_service_profile_sso_ticket.json b/src/test/resources/mgmt/self_service_profile_sso_ticket.json new file mode 100644 index 000000000..8b8c3e83e --- /dev/null +++ b/src/test/resources/mgmt/self_service_profile_sso_ticket.json @@ -0,0 +1,3 @@ +{ + "ticket": "https://example.auth0.com/self-service/connections-flow?ticket=ticket-1234" +} diff --git a/src/test/resources/mgmt/self_service_profile_sso_ticket_request.json b/src/test/resources/mgmt/self_service_profile_sso_ticket_request.json new file mode 100644 index 000000000..17f7af82d --- /dev/null +++ b/src/test/resources/mgmt/self_service_profile_sso_ticket_request.json @@ -0,0 +1,41 @@ +{ + "connection_config": { + "name": "okta", + "display_name": "okta connection", + "is_domain_connection": true, + "show_as_button": true, + "metadata": { + "key1":"value1" + }, + "options":{ + "icon_url":"url", + "domain_aliases":[ + "acme.corp", + "okta.com" + ], + "idpinitiated": { + "enabled": true, + "client_id": "client-1", + "client_protocol": "oauth2", + "client_authorizequery": "response_type=code&scope=openid%20profile%20email" + } + } + }, + "enabled_clients": [ + "client-1" + ], + "enabled_organizations": [ + { + "organization_id": "org_1", + "assign_membership_on_login": true, + "show_as_button": true + } + ], + "ttl_sec": 0, + "domain_aliases_config": { + "domain_verification": "none" + }, + "provisioning_config": { + "scopes": ["get:users"] + } +} diff --git a/src/test/resources/mgmt/self_service_profiles_list.json b/src/test/resources/mgmt/self_service_profiles_list.json new file mode 100644 index 000000000..53001be84 --- /dev/null +++ b/src/test/resources/mgmt/self_service_profiles_list.json @@ -0,0 +1,64 @@ +[ + { + "id": "id1", + "name": "test1", + "description": "This is for testing", + "user_attributes": [ + { + "name": "Phone", + "description": "This is Phone Number", + "is_optional": true + } + ], + "allowed_strategies": [ + "google-apps" + ], + "created_at": "2024-12-16T15:26:39.015Z", + "updated_at": "2024-12-16T15:28:04.933Z" + }, + { + "id": "id2", + "name": "Test2", + "description": "This is for Test2", + "user_attributes": [ + { + "name": "Phone", + "description": "This is Phone Number", + "is_optional": true + }, + { + "name": "UserName", + "description": "This is User Name", + "is_optional": true + } + ], + "allowed_strategies": [ + "oidc" + ], + "created_at": "2024-12-16T15:29:06.119Z", + "updated_at": "2024-12-16T15:29:06.119Z" + }, + { + "id": "id3", + "name": "Test3", + "description": "This is a Test3", + "user_attributes": [ + { + "name": "Name", + "description": "Name Field", + "is_optional": true + } + ], + "allowed_strategies": [ + "oidc" + ], + "created_at": "2024-12-20T09:32:13.885Z", + "updated_at": "2024-12-20T09:32:13.885Z", + "branding": { + "logo_url": "https://www.google.com", + "colors": { + "primary": "#ffffff" + } + } + } +] diff --git a/src/test/resources/mgmt/session.json b/src/test/resources/mgmt/session.json new file mode 100644 index 000000000..07251c3ca --- /dev/null +++ b/src/test/resources/mgmt/session.json @@ -0,0 +1,30 @@ +{ + "id": "sessionId1", + "user_id": "userId1", + "created_at": "2024-09-04T06:41:46.145Z", + "updated_at": "2024-09-04T06:41:46.621Z", + "authenticated_at": "2024-09-04T06:41:46.145Z", + "authentication": { + "methods": [ + { + "name": "federated", + "timestamp": "2024-09-04T06:41:46.145Z" + } + ] + }, + "idle_expires_at": "2024-09-07T06:41:46.622Z", + "expires_at": "2024-09-11T06:41:46.145Z", + "device": { + "initial_user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36", + "initial_asn": "1234", + "initial_ip": "134.1.15.0", + "last_user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36", + "last_ip": "134.1.15.0", + "last_asn": "1234" + }, + "clients": [ + { + "client_id": "clientId1" + } + ] +} diff --git a/src/test/resources/mgmt/tenant.json b/src/test/resources/mgmt/tenant.json index 6fd8a1b21..0c7cd8b67 100644 --- a/src/test/resources/mgmt/tenant.json +++ b/src/test/resources/mgmt/tenant.json @@ -29,5 +29,30 @@ "support_url": "https://mycompany.org/support", "allowed_logout_urls": [ "https://mycompany.org/logoutCallback" - ] + ], + "session_cookie": { + "mode": "persistent" + }, + "acr_values_supported": ["string1", "string2"], + "pushed_authorization_requests_supported": true, + "remove_alg_from_jwks": true, + "mtls": { + "enable_endpoint_aliases": true + }, + "default_token_quota": { + "clients": { + "client_credentials": { + "per_day": 100, + "per_hour": 20, + "enforce": true + } + }, + "organizations": { + "client_credentials": { + "per_day": 100, + "per_hour": 20, + "enforce": true + } + } + } } diff --git a/src/test/resources/mgmt/user_attribute_profile.json b/src/test/resources/mgmt/user_attribute_profile.json new file mode 100644 index 000000000..fb73013ec --- /dev/null +++ b/src/test/resources/mgmt/user_attribute_profile.json @@ -0,0 +1,30 @@ +{ + "id": "uap_1234567890", + "name": "This is just a test", + "user_id": { + "oidc_mapping": "sub", + "saml_mapping": [ + "urn:oid:0.9.10.10.100.1.1" + ], + "scim_mapping": "userName" + }, + "user_attributes": { + "username": { + "label": "test User", + "description": "This is just a test", + "oidc_mapping": { + "mapping": "preferred_username", + "display_name": "UserName" + }, + "saml_mapping":["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"], + "scim_mapping":"displayName", + "auth0_mapping": "testUser", + "profile_required": false, + "strategy_overrides": { + "oidc": { + "scim_mapping":"name.givenName" + } + } + } + } +} diff --git a/src/test/resources/mgmt/user_attribute_profile_template.json b/src/test/resources/mgmt/user_attribute_profile_template.json new file mode 100644 index 000000000..0034bbfa6 --- /dev/null +++ b/src/test/resources/mgmt/user_attribute_profile_template.json @@ -0,0 +1,33 @@ +{ + "id": "auth0-generic", + "display_name": "A standard user attribute profile template", + "template": { + "name": "This is just a test", + "user_id": { + "oidc_mapping": "sub", + "saml_mapping": [ + "urn:oid:0.9.10.10.100.1.1" + ], + "scim_mapping": "userName" + }, + "user_attributes": { + "username": { + "label": "test User", + "description": "This is just a test", + "oidc_mapping": { + "mapping": "preferred_username", + "display_name": "UserName" + }, + "saml_mapping":["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"], + "scim_mapping":"displayName", + "auth0_mapping": "testUser", + "profile_required": false, + "strategy_overrides": { + "oidc": { + "scim_mapping":"name.givenName" + } + } + } + } + } +} diff --git a/src/test/resources/mgmt/user_attribute_profile_templates_list.json b/src/test/resources/mgmt/user_attribute_profile_templates_list.json new file mode 100644 index 000000000..a21ae3d3d --- /dev/null +++ b/src/test/resources/mgmt/user_attribute_profile_templates_list.json @@ -0,0 +1,39 @@ +{ + "user_attribute_profile_templates": [ + { + "id": "auth0-generic", + "display_name": "Auth0 Generic User Attribute Profile Template", + "template": { + "name": "This is just a test", + "user_id": { + "oidc_mapping": "sub", + "saml_mapping": [ + "urn:oid:0.9.10.10.100.1.1" + ], + "scim_mapping": "userName" + }, + "user_attributes": { + "username": { + "label": "test User", + "description": "This is just a test", + "oidc_mapping": { + "mapping": "preferred_username", + "display_name": "UserName" + }, + "saml_mapping": [ + "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" + ], + "scim_mapping": "displayName", + "auth0_mapping": "testUser", + "profile_required": false, + "strategy_overrides": { + "oidc": { + "scim_mapping": "name.givenName" + } + } + } + } + } + } + ] +} diff --git a/src/test/resources/mgmt/user_attribute_profiles_list.json b/src/test/resources/mgmt/user_attribute_profiles_list.json new file mode 100644 index 000000000..6eb4f57d6 --- /dev/null +++ b/src/test/resources/mgmt/user_attribute_profiles_list.json @@ -0,0 +1,95 @@ +{ + "user_attribute_profiles": [ + { + "id": "uap_1234567890", + "name": "This is just a test", + "user_id": { + "oidc_mapping": "sub", + "saml_mapping": [ + "urn:oid:0.9.10.10.100.1.1" + ], + "scim_mapping": "userName" + }, + "user_attributes": { + "username": { + "label": "test User", + "description": "This is just a test", + "oidc_mapping": { + "mapping": "preferred_username", + "display_name": "UserName" + }, + "saml_mapping":["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"], + "scim_mapping":"displayName", + "auth0_mapping": "testUser", + "profile_required": false, + "strategy_overrides": { + "oidc": { + "scim_mapping":"name.givenName" + } + } + } + } + }, + { + "id": "uap_123456789012345", + "name": "Updated Test Organization", + "user_id": { + "oidc_mapping": "sub", + "saml_mapping": [ + "urn:oid:0.9.10.10.100.1.1" + ], + "scim_mapping": "userName" + }, + "user_attributes": { + "username": { + "label": "test User", + "description": "This is just a test", + "oidc_mapping": { + "mapping": "preferred_username", + "display_name": "Display Name" + }, + "auth0_mapping": "testUser", + "profile_required": false + } + } + }, + { + "id": "uap_1234", + "name": "This is another test", + "user_id": { + "oidc_mapping": "sub", + "saml_mapping": [ + "urn:oid:0.9.10.10.100.1.1" + ], + "scim_mapping": "userName", + "strategy_overrides": { + "google-apps": { + "oidc_mapping": "email" + } + } + }, + "user_attributes": { + "username": { + "label": "test User", + "description": "This is just a test", + "oidc_mapping": { + "mapping": "preferred_username", + "display_name": "Display Name" + }, + "auth0_mapping": "testUser", + "profile_required": false, + "strategy_overrides": { + "okta": { + "oidc_mapping": { + "mapping": "${context.userinfo.groups}", + "display_name": "groups" + } + } + } + } + } + } + ], + "next": "Fe26.2*API2_1758785444*34b68e78fd693520c028d0ea61ae32653a36ca05d3da972107bb12a581eea9bb*" + +} diff --git a/src/test/resources/mgmt/user_refresh_tokens.json b/src/test/resources/mgmt/user_refresh_tokens.json new file mode 100644 index 000000000..1b4dc7d0e --- /dev/null +++ b/src/test/resources/mgmt/user_refresh_tokens.json @@ -0,0 +1,57 @@ +{ + "tokens": [ + { + "id": "tokenId1", + "user_id": "userId1", + "created_at": "2024-06-26T09:10:26.643Z", + "idle_expires_at": "2024-06-26T09:10:27.131Z", + "expires_at": "2024-07-03T09:10:26.643Z", + "device": { + "initial_asn": "1234", + "initial_ip": "203.0.113.1", + "initial_user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36", + "last_user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36", + "last_ip": "203.0.113.1", + "last_asn": "1234" + }, + "client_id": "clientId1", + "session_id": "sessionId1", + "rotating": false, + "resource_servers": [ + { + "audience": "https://api.example.com", + "scopes": "offline_access" + } + ], + "last_exchanged_at": "2024-07-03T09:10:26.643Z" + }, + { + "id": "tokenId2", + "user_id": "userId1", + "created_at": "2024-06-26T09:10:26.643Z", + "updated_at": "2024-06-26T09:10:27.131Z", + "idle_expires_at": "2024-06-26T09:10:27.131Z", + "expires_at": "2024-07-03T09:10:26.643Z", + "device": { + "initial_asn": "1234", + "initial_ip": "203.0.113.1", + "initial_user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36", + "last_user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36", + "last_ip": "203.0.113.1", + "last_asn": "1234" + }, + "client_id": "clientId2", + "session_id": "sessionId2", + "rotating": true, + "resource_servers": [ + { + "audience": "https://api.example.com", + "scopes": "offline_access" + } + ], + "last_exchanged_at": "2024-07-03T09:10:26.643Z" + } + ], + "next": "token1", + "total": 11 +} diff --git a/src/test/resources/mgmt/user_sessions.json b/src/test/resources/mgmt/user_sessions.json new file mode 100644 index 000000000..71c9b754f --- /dev/null +++ b/src/test/resources/mgmt/user_sessions.json @@ -0,0 +1,36 @@ +{ + "sessions": [ + { + "id": "sessionId1", + "user_id": "userId1", + "created_at": "2024-06-26T09:10:26.643Z", + "updated_at": "2024-06-26T09:10:27.131Z", + "authenticated_at": "2024-06-26T09:10:26.643Z", + "authentication": { + "methods": [ + { + "name": "pwd", + "timestamp": "2024-06-26T09:10:26.643Z" + } + ] + }, + "idle_expires_at": "2024-06-26T09:40:27.131Z", + "expires_at": "2024-07-03T09:10:26.643Z", + "device": { + "initial_user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36", + "initial_asn": "1234", + "initial_ip": "203.0.113.1", + "last_user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36", + "last_ip": "203.0.113.1", + "last_asn": "1234" + }, + "clients": [ + { + "client_id": "clientId1" + } + ] + } + ], + "next": "sessionId1", + "total": 9 +}